You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux共享内存创建遇权限拒绝、段错误及映射失败问题求助

解决共享内存实现考拉兹猜想的权限、段错误和映射问题

嘿,作为Linux新手能尝试用共享内存实现跨进程通信已经很棒了!咱们来一步步拆解你代码里的坑,这些都是刚接触POSIX共享内存时很容易踩的:

1. 共享内存对象命名不符合规范

Linux下POSIX共享内存的名字必须以斜杠/开头,比如"/collatz_shm",你用的"name"不符合规则,这会直接导致shm_open触发权限拒绝或者找不到对象的问题。

2. 父进程shm_open未正确获取文件描述符

你在父进程里写了shm_open(obj,O_RDONLY,S_IRWXU);但完全没把返回值赋值给fd,fd还是初始的0(对应标准输入),用这个无效的文件描述符去调用mmap,不失败才怪!正确写法应该是:

fd = shm_open(obj, O_RDONLY, 0); // 只读打开不需要传mode参数
if (fd == -1) {
    perror("Parent shm_open error");
    exit(EXIT_FAILURE);
}

3. sprintf重复覆盖导致输出不全/段错误

你每次循环都用sprintf(ptr1,"%d, ",num);,这会一直覆盖共享内存的起始位置,最后只能看到序列的最后一个数。如果序列太长还会溢出共享内存,触发段错误。咱们得维护一个偏移量,每次追加内容:

// 子进程里初始化偏移量
size_t offset = 0;
// 先写入初始数字
offset += snprintf((char*)ptr1 + offset, page_size - offset, "%d, ", num);
while(num != 1) {
    if(num%2 == 0) num = num / 2;
    else num = (num * 3) + 1;
    // 用snprintf确保不会溢出共享内存
    ssize_t written = snprintf((char*)ptr1 + offset, page_size - offset, "%d, ", num);
    if(written < 0) break;
    offset += written;
    if(offset >= page_size) {
        printf("共享内存不够用啦,提前停止\n");
        break;
    }
}

4. 缺少关键的错误检查和资源清理

  • 所有shm_open、mmap、ftruncate调用都要检查返回值,用perror打印具体错误,不然出问题根本不知道哪里错了
  • 使用完共享内存文件描述符后要调用close(fd),避免资源泄漏
  • 子进程和父进程mmap后都要调用munmap释放映射的内存
  • 父进程mmap后要检查是否返回MAP_FAILED,别硬着头皮继续操作

修正后的完整代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<string.h>

int main(int argc,char** argv) {
    pid_t pid;
    pid = fork();
    const size_t page_size = 4096;
    // 共享内存名必须以/开头
    const char* obj = "/collatz_shm";
    int num;

    if(argc < 2) {
        printf("请传入一个正整数作为参数\n");
        return EXIT_FAILURE;
    }

    num = atoi(argv[1]);
    if(num < 1) {
        printf("请输入大于0的数字\n");
        return EXIT_FAILURE;
    }

    if(pid < 0) {
        perror("Fork失败");
        return EXIT_FAILURE;
    } else if(pid == 0) {
        // 创建共享内存,权限设为所有者读写
        int fd1 = shm_open(obj, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
        if (fd1 == -1) {
            perror("子进程shm_open错误");
            exit(EXIT_FAILURE);
        }

        if(ftruncate(fd1, page_size) == -1) {
            perror("ftruncate设置共享内存大小错误");
            close(fd1);
            shm_unlink(obj);
            exit(EXIT_FAILURE);
        }

        void *ptr1 = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, fd1, 0);
        if(ptr1 == MAP_FAILED) {
            perror("子进程mmap失败");
            close(fd1);
            shm_unlink(obj);
            exit(EXIT_FAILURE);
        }

        size_t offset = 0;
        // 写入初始数字
        offset += snprintf((char*)ptr1 + offset, page_size - offset, "%d, ", num);
        while(num != 1) {
            if(num%2 == 0) 
                num = num / 2;
            else 
                num = (num * 3) + 1;
            // 追加数字,确保不溢出
            ssize_t written = snprintf((char*)ptr1 + offset, page_size - offset, "%d, ", num);
            if(written < 0) break;
            offset += written;
            if(offset >= page_size) {
                printf("共享内存已满,提前停止计算\n");
                break;
            }
        }

        // 子进程清理资源
        munmap(ptr1, page_size);
        close(fd1);
        exit(EXIT_SUCCESS);
    } else {
        // 等待子进程完成计算
        wait(NULL);

        int fd = shm_open(obj, O_RDONLY, 0);
        if (fd == -1) {
            perror("父进程shm_open错误");
            return EXIT_FAILURE;
        }

        void *ptr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
        if(ptr == MAP_FAILED) {
            perror("父进程mmap失败");
            close(fd);
            shm_unlink(obj);
            return EXIT_FAILURE;
        }

        printf("考拉兹序列: %s\n", (char*)ptr);

        // 父进程清理资源
        munmap(ptr, page_size);
        close(fd);
        shm_unlink(obj);
    }
    return EXIT_SUCCESS;
}

编译运行说明

编译时需要链接rt库(POSIX共享内存属于实时扩展库):

gcc collatz_shm.c -o collatz_shm -lrt

运行时传入一个正整数参数:

./collatz_shm 10

这样就能解决你遇到的权限拒绝、段错误和映射失败问题,正常输出考拉兹序列啦!

内容的提问来源于stack exchange,提问作者Shary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:52:32