C - 创建/写入/读取命名管道

Posted

技术标签:

【中文标题】C - 创建/写入/读取命名管道【英文标题】:C - Create/Write/Read named pipe 【发布时间】:2016-05-28 18:48:10 【问题描述】:

我想创建一个命名管道,然后写入它,然后我想读取它。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#define FIFO "fifo0001"
int main(intargc, char *argv[])
    char input[256];
    FILE *fp;
    char str[50];
    printf("Please write some text:\n");
    scanf("%s", input);
    unlink(FIFO); /* Because it already exists, unlink it before */
    umask(0);
    if(mkfifo(FIFO, 0666) == -1)
        printf("Something went wrong");
        return EXIT_FAILURE;
    
    if((fp = fopen(FIFO, "a")) == NULL)
        printf("Something went wrong");
        return EXIT_FAILURE;
    
    fprintf(fp, "%s", input);
    if(fgets(str, 50, fp) != NULL)
        puts(str);
    
    fclose(fp);
    return EXIT_SUCCESS;

在我写完一篇文章后,什么都没有发生了。而且没有消息。我必须用 STRG C 退出程序。有人知道出了什么问题吗?我必须使用函数 mkfifo、fopen、fprintf、fgets 和 fclose。如果我可以将它们保留在代码中,那就太好了。

【问题讨论】:

FIFO 不能以这种方式工作。您需要两个程序,一个(仅)写入 FIFO,另一个(仅)读取。 是的,我知道那是我的目标,但我编写了一个程序来测试它。但是当我删除阅读部分时,会出现同样的问题 您的程序将阻塞,直到另一个程序打开 FIFO 的另一端进行读取。 Why does my program hang when opening a mkfifo-ed pipe?的可能重复 @AndrewHenle 他打电话给umask(0) 【参考方案1】:

FIFO 不适用于仅一个线程。 在执行写入打开之前,您将在读取打开时被阻塞,反之亦然,因此您需要在 RDWR(非便携式)模式下打开,或者在一个线程中使用 RDONLY 而在另一个线程中使用 WRONLY,否则您会被阻塞.

例如:

fp = fopen(FIFO, "r+");

那么您将需要写入不超过 FIFO 缓冲区的大小(即 ulimit -p * 512 ?)(否则您会被阻塞)。之后,您只需要阅读您所写的内容即可。

总而言之,这应该可行(尽管它不是使用 FIFO 的常用方法):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#define FIFO "fifo0001"

int main(int argc, char *argv[])
    char input[256] = "hw";
    FILE *fp;
    char str[50];
    printf("Please write some text:\n");
    scanf("%s", input); //!!!

    size_t input_len = strlen(input);

    unlink(FIFO); /* Because it already exists, unlink it before */
    umask(0);
    if(mkfifo(FIFO, 0666) == -1)
        printf("Something went wrong");
        return EXIT_FAILURE;
    
    if((fp = fopen(FIFO, "r+")) == NULL)
        printf("Something went wrong");
        return EXIT_FAILURE;
    
    fprintf(fp, "%s", input);
    if(fgets(str, input_len+1, fp) != NULL)
        puts(str);
    
    fclose(fp);
    return EXIT_SUCCESS;

【讨论】:

以上是关于C - 创建/写入/读取命名管道的主要内容,如果未能解决你的问题,请参考以下文章

在多个进程写入时读取命名管道

程序打开同一个命名管道并用 C 多次写入

为啥在没有人阅读后继续写入命名管道?

如何避免命名管道中的多个作者?

命名管道类似于“mkfifo”创建,但双向

如何写入命名管道而不等待读取管道