oos*_*111 0 c linux posix fork pipe
我有以下程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/wait.h>
int main()
{
int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = "-w";
argv[2] = NULL;
pipe(p);
if (fork() == 0)
{
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
execvp(argv[0], argv);
}
else
{
close(p[0]);
write(p[1], "hello world\n", 12);
}
fprintf(stdout, "hello world\n");
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时:
$ gcc a.c
$ ./a.out
Run Code Online (Sandbox Code Playgroud)
我得到以下内容:
hello world
$ 2
_ // the cursor is flickering here
Run Code Online (Sandbox Code Playgroud)
输入后Enter,程序退出。这是什么原因呢?另外,如果我像这样交换父进程和子进程中的内容:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/wait.h>
int main()
{
int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = "-w";
argv[2] = NULL;
pipe(p);
if (fork() == 0)
{
close(p[0]);
write(p[1], "hello world\n", 12);
}
else
{
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
execvp(argv[0], argv);
}
fprintf(stdout, "hello world\n");
}
Run Code Online (Sandbox Code Playgroud)
我得到了预期的输出:
hello world
2
$
Run Code Online (Sandbox Code Playgroud)
该程序已退出,可以获取下一个命令。第一个程序有什么问题?
如果您非常仔细地查看输出,您将看到程序已退出:
hello world
$ 2
_ // the cursor is flickering here
Run Code Online (Sandbox Code Playgroud)
看看如何$打印?这是您的shell像往常一样等待输入。通过按,enter您只需在shell中输入一个空白命令并获得第二个$提示。
2那里在做什么?那wc是输出。您的程序实际上并不是在等待wc退出。这意味着你的程序退出之前 wc做的,所以外壳简历,打印其提示,只有那么做wc出口和打印2。
要解决此问题,您可能需要添加某种wait调用来等待父级中的子进程。