为什么在我“编写”FIFO特殊文件或在程序中创建FIFO特殊文件后,shell提示符不会出现?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么在我“编写”FIFO特殊文件或在程序中创建FIFO特殊文件后,shell提示符不会出现?相关的知识,希望对你有一定的参考价值。

我正在学习Linux中的命名管道并编写以下程序来试用它。

以下程序创建名为“test.fifo”的FIFO特殊文件,然后创建两个子进程以从该命名管道读取和写入。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>

int main() {
    pid_t pid[2];

    // Create FIFO special file
    mkfifo("test.fifo", 0644);

    pid[0] = fork();
    if (pid[0] < 0) {
        printf("Fail to fork child process #0
");
        return 1;
    } else if (pid[0] == 0) {
        // Open FIFO special file in read mode
        int in = open("test.fifo", O_RDONLY);

        // Read data
        char buf[256];
        read(in, buf, 256);
        printf("Child process #0 received: %s
", buf);

        // Close pipe
        close(in);
        return 0;
    }

    pid[1] = fork();
    if (pid[1] < 0) {
        printf("Fail to fork child process #1
");
        return 1;
    } else if (pid[1] == 0) {
        // Open FIFO special file in write mode
        int out = open("test.fifo", O_WRONLY);

        // Write data
        char buf[256] = {0};
        strcpy(buf, "Hello world");
        write(out, buf, 256);

        // Close pipe
        close(out);
        return 0;
    }

    return 0;
}

有时这个程序运行正常。但有时在这个程序运行后,我的shell提示会消失。

MyUserName@MyHostName:~$ ./a.out
MyUserName@MyHostName:~$ Child process #0 received: Hello world
(This is an empty line, no shell prompt occurs)

我尝试在空行中键入并运行命令ls,该命令有效。所以程序似乎已经成功退出,而且只是shell提示不会发生。

如果我运行命令cat test.fifo,也会发生同样的事情。

MyUserName@MyHostName:~$ cat test.fifo
(This is an empty line, no shell prompt occurs)

发生了什么,为什么会发生这种情况?

答案

由于父程序没有wait(2)让孩子们完成,当它做exit(2)(在主要的最后一个return 0;)时,shell显示提示。但是你不能控制(甚至不知道)子节点是否已完成打印输出,因此shell提示可能会被其中一个子节点的输出所覆盖。但是shell总是输出提示符,但是由于它不跟随新行(光标保持在同一行),所以可以使它被子项的输出覆盖。

尝试将以下内容放在最后一个return 0;之前:

wait(NULL);
wait(NULL); /* as you did two fork()s you can make up to two wait()s */

然后,程序终止将与孩子同步。

另一答案

感谢所有的评论!

就像Charles Duffy所说的那样,shell提示已经被打印 - 它是./a.out调用之后的那个。我忘了在父进程中使用wait()。因此,如果父进程在子进程之前退出,则shell提示符将在“子进程#0 ...”之前打印。

至于cat test.fifo,我在描述中犯了一个错误。如果我运行cat test.fifo,不仅没有出现shell提示符,而且如果我在空行上键入并运行它,ls命令也将无法工作。这是因为cat命令试图在读取模式下打开FIFO特殊文件,但没有进程尝试在写入模式下打开FIFO特殊文件。

https://linux.die.net/man/7/fifo我们知道,“在数据传递之前,FIFO必须在两端打开(读取和写入)。通常,打开FIFO块直到另一端打开。”因此cat test.fifo命令实际上已被阻止且尚未退出,因此不会发生shell提示。

以上是关于为什么在我“编写”FIFO特殊文件或在程序中创建FIFO特殊文件后,shell提示符不会出现?的主要内容,如果未能解决你的问题,请参考以下文章

哪个是安全的,使用一次 required 或在 codeigniter 的帮助程序中创建一个函数?

在 Python 中创建一个临时 FIFO(命名管道)?

如何在C中创建线程的被动等待FIFO?

在特定文件夹android中创建文本文件

如何在目标 c ipad 应用程序中创建要写入的新文本文件

难以访问在 Interface Builder .xib 文件中创建的 UITableViewCell