如何使用管道连接C中的两个子进程
how to use pipe to connect two child process in C
我正在自学一本OS课本并做作业:
Write a program that creates two children, and connects the standard output of one to the standard input of the other, using the pipe() system call.
然后我试着这样写我的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc < 0)
{
fprintf(stderr, "fork failed");
exit(1);
}
else if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff1, sizeof buff1);
puts("this is a message from child 1");
write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff2, sizeof buff2);
puts("this is a message from child 2");
write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
}
}
return 0;
}
如果一切顺利。我应该在 txt 文件中看到来自 child1 或 child2 的消息。但是当我 运行 这段代码时什么也没有发生。
但是如果我像这样删除任何一个读取语句:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc < 0)
{
fprintf(stderr, "fork failed");
exit(1);
}
else if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
//int n = read(STDIN_FILENO, buff1, sizeof buff1);
puts("this is a message from child 1");
//write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff2, sizeof buff2);
puts("this is a message from child 2");
write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
}
}
return 0;
}
或者像这样
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc < 0)
{
fprintf(stderr, "fork failed");
exit(1);
}
else if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff1, sizeof buff1);
puts("this is a message from child 1");
write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
//int n = read(STDIN_FILENO, buff2, sizeof buff2);
puts("this is a message from child 2");
//write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
}
}
return 0;
}
我可以从双方的 txt 文件中看到正确的输出。
我想知道我的代码中发生了什么,第一种情况出了什么问题?
代码中的几个问题:
您的两个子进程都在从管道读取时阻塞,但没有任何内容写入其中,因此它们永远阻塞。解决方法是在读取之前写入管道。
需要 fflush
以确保 stdout
缓冲区写入 STDOUT_FILENO
。 stdout
在连接到终端时为 line-buffered,否则为 block-buffered(在调用 main
之前确定),因此 puts
在 stdout
没有连接到程序 start-up 的终端。
父进程应该等待子进程终止。 If/when 父进程是会话领导者并且它终止,内核将 SIGHUP
发送到其组中的所有(子)进程。 More details.
修复的代码:
int main() {
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
fflush(stdout);
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
puts("this is a message from child 1");
fflush(stdout);
int n = read(STDIN_FILENO, buff1, sizeof buff1);
write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
fflush(stdout);
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
puts("this is a message from child 2");
fflush(stdout);
int n = read(STDIN_FILENO, buff2, sizeof buff2);
write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
waitpid(rc, &rc, 0);
waitpid(rc2, &rc2, 0);
}
}
return 0;
}
我正在自学一本OS课本并做作业:
Write a program that creates two children, and connects the standard output of one to the standard input of the other, using the pipe() system call.
然后我试着这样写我的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc < 0)
{
fprintf(stderr, "fork failed");
exit(1);
}
else if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff1, sizeof buff1);
puts("this is a message from child 1");
write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff2, sizeof buff2);
puts("this is a message from child 2");
write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
}
}
return 0;
}
如果一切顺利。我应该在 txt 文件中看到来自 child1 或 child2 的消息。但是当我 运行 这段代码时什么也没有发生。 但是如果我像这样删除任何一个读取语句:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc < 0)
{
fprintf(stderr, "fork failed");
exit(1);
}
else if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
//int n = read(STDIN_FILENO, buff1, sizeof buff1);
puts("this is a message from child 1");
//write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff2, sizeof buff2);
puts("this is a message from child 2");
write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
}
}
return 0;
}
或者像这样
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc < 0)
{
fprintf(stderr, "fork failed");
exit(1);
}
else if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
int n = read(STDIN_FILENO, buff1, sizeof buff1);
puts("this is a message from child 1");
write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
//int n = read(STDIN_FILENO, buff2, sizeof buff2);
puts("this is a message from child 2");
//write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
}
}
return 0;
}
我可以从双方的 txt 文件中看到正确的输出。 我想知道我的代码中发生了什么,第一种情况出了什么问题?
代码中的几个问题:
您的两个子进程都在从管道读取时阻塞,但没有任何内容写入其中,因此它们永远阻塞。解决方法是在读取之前写入管道。
需要 fflush
以确保stdout
缓冲区写入STDOUT_FILENO
。stdout
在连接到终端时为 line-buffered,否则为 block-buffered(在调用main
之前确定),因此puts
在stdout
没有连接到程序 start-up 的终端。父进程应该等待子进程终止。 If/when 父进程是会话领导者并且它终止,内核将
SIGHUP
发送到其组中的所有(子)进程。 More details.
修复的代码:
int main() {
printf("parent in pid: (%d)\n", (int)getpid());
fflush(stdout);
int p1[2], p2[2];
pipe(p1);
pipe(p2);
char buff1[100];
char buff2[100];
int rc = fork();
if (rc == 0)
{
int fd = open("test1.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd);
printf("entering child1 process at pid : (%d)\n", (int)getpid());
fflush(stdout);
dup2(p1[0], STDIN_FILENO);
dup2(p2[1], STDOUT_FILENO);
puts("this is a message from child 1");
fflush(stdout);
int n = read(STDIN_FILENO, buff1, sizeof buff1);
write(fd, buff1, n);
}
else
{
int rc2 = fork();
if (rc2 == 0)
{
int fd2 = open("test2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
printf("%d\n", fd2);
printf("entering child2 process at pid : (%d)\n", (int)getpid());
fflush(stdout);
dup2(p2[0], STDIN_FILENO);
dup2(p1[1], STDOUT_FILENO);
puts("this is a message from child 2");
fflush(stdout);
int n = read(STDIN_FILENO, buff2, sizeof buff2);
write(fd2, buff2, n);
}
else
{
printf("final parent in pid: (%d)\n", (int)getpid());
waitpid(rc, &rc, 0);
waitpid(rc2, &rc2, 0);
}
}
return 0;
}