【问题标题】:Can a text file used as a pipe?可以将文本文件用作管道吗?
【发布时间】:2015-12-03 14:46:46
【问题描述】:

我写了一些代码来练习管道的使用,遇到了一些问题。

对于下面的代码,我尝试创建一个命名管道来写入/读取。但是如果我的文本文件中有一些单词,我的代码就不起作用。我预计输出会打印出文本文件中的单词和我写入的字符串。我不能使用 .txt 文件作为管道吗?如何使用管道修改文本文件?感谢您的帮助!

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

#define MAX 100

int main()
{
    int fd;
    char *myfifo = "pipe_tx2.txt";
    char buf[MAX];

    /* create the fifo */
    mkfifo(myfifo, 666);

    /* write string to the pipe */
    fd = open(myfifo, O_WRONLY);
    write(fd, "hello", sizeof("hello"));
    close(fd);

    /* read and display message from pipe */
    fd = open(myfifo, O_RDONLY);
    read(fd, buf, MAX);
    printf("we got: %s\n", buf);
    close(fd);

    /* remove the pipe */
    unlink(myfifo);

    return 0;
}

【问题讨论】:

  • 您没有检查来自mkfifo()write()read() 的返回值。所以你不知道什么有效,什么无效。你甚至不知道你的open() 调用是否成功。
  • 我不确定我是否理解您所说的“如果我的文本文件中有一些单词,我的代码将无法正常工作”是什么意思。您是说您有一个与您尝试创建的 FIFO 同名的现有常规文件吗?如果是这样,那么不,那绝对行不通。 FIFO 是文件的一种特殊种类,而不是文件的特殊用途
  • 666 是十进制,但应该是八进制 0666
  • 如果已有同名文件,mkfifo 将返回-1(失败)并设置errno = EEXIST
  • 您的意思是使用“.txt”扩展名来命名命名管道?当然可以,标准 Unix 文件系统中没有文件扩展名的概念,任何字符串都可以命名任何类型的 file

标签: c unix pipe


【解决方案1】:

您的代码中存在一些问题。首先正如大家所注意到的,您的访问权限是错误的,请在八进制中指定它们0666

但是,最糟糕的是,命名管道上的打开/读/写语义与常规文件不同。 open 用于编写命名管道被阻塞,直到有人打开它进行阅读,反之亦然。所以单个进程不能以这种方式使用命名管道(请记住,管道通常设计用于在进程之间进行通信)。你需要的是先以非阻塞模式打开读取,然后立即将模式设置为阻塞,然后再打开写入,这样写入部分就可以使用了。

另一个问题是您没有发送正确的数据。您应该使用strlen 来获取 C 字符串的长度并添加一个计数并包含 NUL 终止字符,因此在另一部分读取完整的 C 字符串将是正确的。

【讨论】:

    【解决方案2】:

    你的直接问题是你使用666而不是0666作为FIFO的模式,这意味着你没有读取它的权限。带有更多错误检查的代码将证明这一点:

    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    #define MAX 100
    
    int main()
    {
        int pid;
        char *myfifo = "pipe_tx2.txt";
    
        unlink(myfifo);             /* if it already exists */
        /* create the fifo */
        if (mkfifo(myfifo, 666)) {
            perror(myfifo);
            return 1;
        }
    
        pid = fork();
        if (pid < 0) {
            perror("fork");
            return 1;
        }
    
        if (!pid) {
            /* child process - read and display message from pipe */
            char buf[MAX];
            int fd = open(myfifo, O_RDONLY);
            int bytes_read;
            if (fd < 0) {
                perror(myfifo);
                return 1;
            }
    
            bytes_read = read(fd, buf, MAX);
            if (bytes_read < 0) {
                perror("read");
                return 1;
            }
            printf("We got: %*s\n", bytes_read, buf);
            close(fd);
            return 0;
        }
    
        {
            /* parent process - write string to the pipe */
            static const char message[] = "hello";
            sleep(2);               /* just to show that the child blocks until we write */
    
            int fd = open(myfifo, O_WRONLY);
            int bytes_written;
            if (fd < 0) {
                perror(myfifo);
                return 1;
            }
            write(fd, message, sizeof message);
            if (bytes_written <= 0) {
                perror("write");
                return 1;
            }
            close(fd);
        }
    
        waitpid(pid, NULL, 0);
    
        /* remove the pipe */
        unlink(myfifo);
    
        return 0;
    }
    

    将模式更改为0666,您将不再从阅读过程中获得pipe_tx2.txt: Permission denied

    【讨论】:

      猜你喜欢
      • 2012-06-12
      • 2021-01-03
      • 1970-01-01
      • 2016-09-23
      • 2021-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多