返回0后,main函数不退出,shmctl不删除段

时间:2013-01-11 16:29:25

标签: c shared-memory

我正在尝试使用共享内存作为管道,我遇到了几个问题:

  1. 我无法删除段
  2. return 0

    之后,主要功能不会退出
    int main()
    {
      int spd[2], pid, rb;
      char buff[4096];
      if (shm_pipe_pipe(spd) < 0)
      {
            perror("shm_pipe_pipe");
            exit(1);
      }
      if (fork())
      {
            rb = shm_pipe_read(spd[0], buff, sizeof(buff));
            if (rb > 0)
                    write(1, buff, rb);
      }
      else
      {
             shm_pipe_write(spd[1], "hello world!\n", sizeof("hello world!\n"));
      }
    
      shm_pipe_close(spd[0]);
      shm_pipe_close(spd[1]);
      printf("end main\n");
      return 0;
    }
    
  3. 最后一个输出是“end main”,但程序没有关闭并返回bash ... 我肯定它与整个共享内存有关:

    shm_pipe_pipe()分配共享内存段和指向共享内存的指针:

    shmid = shmget(key, PIPE_SIZE, IPC_CREAT | IPC_EXCL | 0600);
    buffer = (char*)shmat(pipes_array[i].m_shmid, NULL, 0)) == NULL)
    

    shm_pipe_write and shm_pipe_read只需对共享内存执行memcpy()

    shm_pipe_close() free指向段的指针并删除段:

    shmdt(buffer);
    shmctl(shmid, IPC_RMID, NULL);
    

    我不明白为什么不起作用。

    fork(2) the child inherits the attached shared memory segments.

    之后写在shmdt的手册页中

    所以我尝试在父亲和孩子身上使用shmdt两次,但后来我收到错误

    Invalid argument
    

    打印“{main}”后main()卡住时,我尝试使用ipcs -m查看共享内存的状态,我看到nattch为1,{{1}是0 ... 仅在key ctrl+c之后,内存段才会从main()

    中删除

    我不确定我应该带些什么进一步的信息。我没有写出所有的功能,因为这很多,我认为这不重要......

2 个答案:

答案 0 :(得分:1)

我怀疑你对某事感到困惑。

  

最后一个输出是“end main”

     

shm_pipe_close()free指向段的指针并删除段

然而,正如所写的那样 - 在子块中没有exit - 此代码在父级和子级中运行

  shm_pipe_close(spd[0]);
  shm_pipe_close(spd[1]);
  printf("end main\n");

换句话说,两次(除非孩子在shm_pipe_read停滞,见下文)。如果“删除段”是指单个共享内存实体,那么这可能是无意的。

除此之外,您的结果取决于shm_pipe_readshm_pipe_write是否像管道上的正常阻塞读/写调用一样工作,等待直到在另一端读取或写入数据。我猜你的写作当然不是而不是,而且可能也不是读。

这意味着shm_pipe_write可能会在父级中发生,然后“管道”(实际上是共享的内存网段)会立即被删除。如果这导致shm_pipe_read中的某些内容停止(因为该段已经消失),它可能(如评论中的ring0所述)解释您的问题。

答案 1 :(得分:0)

我认为你的问题就在这里:

 shmid = shmget(key, PIPE_SIZE, IPC_CREAT | IPC_EXCL | 0600);

更改权限,以便子和父可以访问共享内存段:

 shmid = shmget(key, PIPE_SIZE, IPC_CREAT | IPC_EXCL | 0666);

因为我不确切知道你的功能在做什么......这是一个类似的程序,你可以参考看看你是否有其他错误(顺便说一下 - 我把权限改为0600,我可以看到主要过程完成,但孩子挂起):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, char * argv[])
{
    key_t key = 1111;
    int shmid;
    char *buff;
    char *s;
    char *addr = NULL;

    if((shmid = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0666)) < 0 ) {
         perror("shmget");
        return -1;
    }
    if((buff = shmat(shmid, addr, 0)) == (char *)-1) {
        perror("shmat");
        return -1;
    }
    if(fork()){
      printf("I'm the child\n");
      while(strlen(buff) == 0) {}
      for(s = buff; *s != NULL; s++)
        putchar(*s);
      printf("\nChild is done\n");
    }
    else {
      printf("I'm the parent\n");
       strcpy(buff, "hello world!\0");
      printf("Parent is done.\n");
    }
    shmdt(addr);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}