0

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

  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;
    }
    

最后一个输出是“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);

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

它写在 shmdt 的手册页中,经过fork(2) the child inherits the attached shared memory segments.

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

Invalid argument

main()打印“end main”后卡住时,我尝试查看共享内存的状态ipcs -m,我看到nattch是 1,然后key是 0...只有在我之后ctrl+c main(),内存段才被删除ipcs -m

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

4

2 回答 2

1

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

最后一个输出是“end main”

shm_pipe_close() 释放指向该段的指针并删除该段

然而,正如所写的那样——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 在评论中所说)解释您的问题。

于 2013-01-11T17:04:26.763 回答
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;
}
于 2013-01-11T17:54:55.490 回答