【问题标题】:Named pipe creation命名管道创建
【发布时间】:2011-06-06 02:21:26
【问题描述】:

我正在尝试使用命名管道。我有一个读取信息的进程和另一个将信息写入管道的进程。

这是我的阅读器进程的简化代码:

main (int argc, char *argv[]) {
  int fd, mkn;
  char message[100];

  if(unlink("aPipe") == -1) {
      perror("Error unlinking:");
  }


  if((mkn = mknod("aPipe", S_IFIFO, 0)) < 0){
    perror("Error mknod:");
  }

  if(chmod("aPipe", 0660)) {
    perror("Error chmod:");
   }

  if(fd = open("aPipe", O_RDONLY) < 0) {
    perror("Error abriendo el PIPE");
   }

    printf("going to read..\n");

close(fd);
}

但它永远停留在这一行:if(fd = open("aPipe", O_RDONLY) &lt; 0),我真的不明白为什么。

如果你知道哪个手册页说这里发生了什么,请告诉我:)

【问题讨论】:

  • 哪个进程负责创建 FIFO:读取器或写入器(或者应该在任何一个启动之前创建)?如果您的阅读器删除了编写器创建的 FIFO,它将在打开时阻塞,因为它的新管道上没有编写器;相反,如果写入器删除了读取器创建的 FIFO,它将在打开时阻塞,因为没有读取器。此外,您应该使用mkfifo() 而不是mknod()(尽管在大约二十年前,您会使用mknod(),因为mkfifo() 不存在)。

标签: c unix named-pipes


【解决方案1】:

FIFO 有点奇怪; open() 作为作家将阻塞,直到有读者,反之亦然。更糟糕的是,就像真正的管道一样,当写入器关闭其末端时,读取端将永远返回 EOF;您必须关闭并重新打开(阻止下一个读者)。或者你 open(fifo, O_RDWR) 然后你需要一些方法来知道编写器何时完成,例如让它只使用一行或有一个带内 EOF 数据包。

【讨论】:

    【解决方案2】:

    代码如下:

    读者:

    #include <stdio.h>
    #include <unistd.h> 
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    readline(int fd, char *str) {
    int n;
    do {
        n = read(fd, str, 1);
        if(n == -1){
            perror("Error reading:");
        }
    }
    while(n > 0 && (str++) != NULL);
    
    return(n > 0);
    

    }

    main (int argc, char *argv[]) {
    int fd, mkn;
    char message[100];
    
    if(unlink("aPipe") == -1) {
        perror("Error unlinking:");
    }
    
    if((mkn = mknod("aPipe", S_IFIFO, 0)) < 0){
        perror("Error mknod:");
    }
    
    if(chmod("aPipe", 0660)) {
        perror("Error chmod:");
    }
    
    if(fd = open("aPipe", O_RDONLY) < 0) {
        perror("Error abriendo el PIPE");
    }
    printf("going to read..\n");
    while(readline(fd,message))
        printf("%s\n", message);
    close(fd);
    }
    

    作者:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    
    main (int argc, char *argv[]) {
    int fd, messagelen,i;
    char message[100];
    
    sprintf(message, "Hello from PID %d", getpid());
    
    messagelen = strlen(message) + 1;
    do {
        fd = open("aPipe", O_WRONLY|O_NDELAY);
        if (fd == -1) {
            perror("opening aPipe:");
            sleep(1);
        }
    }
    while(fd == -1);
    
    for (i = 1; i < 4; i++) {
        if(write(fd, message, messagelen) == -1) {
            perror("Error writing:");
        }
        sleep(3);
    }
    close(fd);
    } 
    

    我也得学makefifo,但是在我明白了这个之后。

    非常感谢您的宝贵帮助!

    【讨论】:

    • 如果你想添加一些东西,你应该编辑你的问题而不是添加答案,除非你自己找到了解决方案并且你实际上是在回答你自己的问题。
    【解决方案3】:

    是否有任何进程写入 FIFO? 如果不是,这是预期的行为,因为您在阻塞模式下打开了 FIFO RDONLY,当前进程将不会继续,直到有进程实际写入 FIFO。

    【讨论】:

    • 是的,我有这个打开管道的过程:fd = open("aPipe", O_WRONLY|O_NDELAY);对 open 的调用是一个 do while(fd == -1);,但无论如何,它总是显示错误:没有这样的设备或地址
    • 一方必须将 O_CREAT 传递给 open() 才能创建管道。
    • 不 mknod 创建管道?
    • 我会使用mkfifo()系统调用来创建一个FIFO。而且,如果您能向我们展示您的协作编写过程的代码,那将会很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-12-21
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-11
    • 2012-07-29
    相关资源
    最近更新 更多