代码之家  ›  专栏  ›  技术社区  ›  Addem

`shmget `无效参数错误--是否仍从上次执行中分配内存?

ipc c
  •  1
  • Addem  · 技术社区  · 2 年前

    我有以下程序来练习使用fork和共享内存。

    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/types.h> 
    #include <unistd.h> 
    #include <sys/wait.h>
    
    #include <sys/shm.h>
    #include <sys/ipc.h>
    
    int main() {
        int bignum = 1000000;
        
        key_t key = ftok(".", 'x');
        int shmid = shmget(key, sizeof(int)*bignum, IPC_CREAT | 0666);
        if (shmid < 0) {
            perror("shmget\n");
            return 1;
        }
        int *arr = shmat(shmid, NULL, 0);
        pid_t c1 = fork();
        if (c1==0) {
            pid_t c2 = fork();
            if (c2==0) {
                pid_t c3 = fork();
                if (c3==0) {
                    arr[0] = 10;
                } else {
                    arr[1] = 11;
                }
                wait(NULL);
                exit(0);
            } else {
                arr[2] = 12;
            }
            wait(NULL);
            exit(0);
        } else {
            arr[3] = 13;
            wait(NULL);
    
            for (int i=0; i<4; i++) printf("%d ", arr[i]);
            printf("\n");
        }
    
    
        shmdt(arr);
        shmctl(shmid, IPC_RMID, NULL);
        exit(0);
    }
    

    我之前使用较少的共享内存运行这个程序,现在增加了它,看看这是否会对程序产生任何影响。当我运行这个时,我得到:

    shmget
    : Invalid argument
    

    我看过这篇文章: C linux shmget Invalid argument

    我试着听从建议,但我不熟悉 ipcs ipcrm 我跑了 ipcs 在终端中,它给了我一些共享内存信息。但我不知道哪个是程序分配的,有很多,我也不知道删除什么是安全的。

    在我看来,你不只是在C程序本身中这样做,这也很奇怪,所以我想知道是否有更好的方法来解决这个问题。我特别不明白为什么打电话给 shmdt shmctl 不要把这当作一个无关紧要的问题。是否有其他方法可以“撤消”内存共享?


    编辑:该问题已关闭,因为它与以下内容相似:

    C - System V - remove shared memory segment

    然而,这使用了我的代码中已经存在的代码——所以它似乎没有回答这个问题。

    1 回复  |  直到 2 年前
        1
  •  1
  •   Ted Lyngmo    2 年前

    旧程序退出后留下了一个较小的共享内存段,因此连接到它并请求更大的内存段失败。您可以通过删除新程序来启动它:

    key_t key = ftok(".", 'x');
    int shmid = shmget(key, 1, 0666); // no IPC_CREAT
    
    if (shmid != -1) { // ok, there was a memory segment there already
        shmctl(shmid, IPC_RMID, NULL); // remove it
    }
    // now create the new one
    shmid = shmget(key, sizeof(int)*bignum, IPC_CREAT | 0666);
    
    推荐文章