如何解决Linux C 中子级和父级之间的管道示例
这看起来很简单,中间的一个管道,父进程会在管道的写端写入管道,子进程会在while循环中从管道中读取,并打印读取的内容,但是我的程序无法停止...
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc,char *argv[]){
int fd[2];
int number;
int write_number[1];
pipe(fd);
int pid;
if ((pid = fork()) >0){
close(fd[0]);
for (int i = 2; i < 36; i++){
*write_number = i;
write(fd[1],write_number,4);
}
printf("write finished from parent process:%d\n",pid);
close(fd[1]);
}else{// child process
close(fd[1]);
while(read(fd[0],&number,4))
printf("The number is %d from child %d\n",number,getpid());
close(fd[0]);
}
exit(0);
}
顺便说一下,这是来自 xv6 类 Unix 系统,但我认为这与 Linux 中的几乎相同,输出:
$ primes
The numbwerite finished from parent prorc eis ss:24
from $ child 4
The number is 3 from child 4
The number is 4 from child 4
The number is 5 from child 4
The number is 6 from child 4
The number is 7 from child 4
The number is 8 from child 4
The number is 9 from child 4
The number is 10 from child 4
The number is 11 from child 4
The number is 12 from child 4
The number is 13 from child 4
The number is 14 from child 4
The number is 15 from child 4
The number is 16 from child 4
The number is 17 from child 4
The number is 18 from child 4
The number is 19 from child 4
The number is 20 from child 4
The number is 21 from child 4
The number is 22 from child 4
The number is 23 from child 4
The number is 24 from child 4
The number is 25 from child 4
The number is 26 from child 4
The number is 27 from child 4
The number is 28 from child 4
The number is 29 from child 4
The number is 30 from child 4
The number is 31 from child 4
The number is 32 from child 4
The number is 33 from child 4
The number is 34 from child 4
The number is 35 from child 4
它没有停止,所以它挂起,但我已经关闭了我应该关闭的文件描述符,所以如果没有读取任何内容,读取系统调用应该返回 0,为什么它仍然挂起,所以任何人都可以帮我一把?谢谢!
解决方法
它确实停止了——在孩子打印“The number is 3 from the child 4”之前,父母退出并在混乱的输出中从shell中产生提示:
$ primes
The numbwerite finished from parent prorc eis ss:24
from $ child 4
The number is 3 from child 4
您可能应该让父进程在带有 wait()
或 waitpid()
函数的循环中等待,以便子进程在父进程退出和 shell 重新提示之前完成。
#include <sys/wait.h>
…
int status;
int corpse;
while ((corpse = wait(&status)) > 0)
print("Child %d died with exit status 0x%.4X\n",corpse,status);
虽然不太可能,但进程有可能有当前程序没有分叉的子进程——而且循环也适用于这种情况。
切线注释:
-
由于您忽略命令行参数,因此最好使用
int main(void)
。 -
exit(0);
不是必需的。您可以省略它,如果您在 C99 或更高版本的模式下编译,该进程将以零退出。这只是main()
函数的特殊规则。就我个人而言,我更喜欢在return 0;
末尾使用显式main()
。 -
你有:
for (int i = 2; i < 36; i++){ *write_number = i; write(fd[1],write_number,4); }
您可以使用:
for (int i = 2; i < 36; i++)
write(fd[1],&i,sizeof(i));
使用 sizeof()
是惯用的;使用 4
容易出错。并且不需要 write_number
数组。
- 标题的选择是常规的。您应该使用
<stdio.h>
、<unistd.h>
和<sys/wait.h>
。您实际上并不需要<sys/types.h>
。内核头文件应该只在编译代码以在内核中运行时使用——这个程序不是内核代码。
你说:
我加了一些像printf("child process is finished")这样的代码,在子条件下打印,但是exit(0)之前没有wait(0),表示子进程没问题,它会从管道关闭,但最后程序没有完成,只是挂在那里似乎在等待输入,我认为这是父退出但不等待孩子退出()的情况,但孩子确实在结束,但他的程序没有完成......最后的困惑
IMO,您的代码应如下所示:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int fd[2];
pipe(fd);
int pid;
if ((pid = fork()) > 0)
{
close(fd[0]);
for (int i = 2; i < 36; i++)
write(fd[1],sizeof(i));
close(fd[1]);
printf("write finished from parent process:%d\n",pid);
int status;
int corpse;
while ((corpse = wait(&status)) > 0)
{
printf("%d: child %d exited with status 0x%.4X\n",(int)getpid(),status);
}
}
else if (pid < 0)
{
fprintf(stderr,"failed to fork\n");
return 1;
}
else
{
int number;
close(fd[1]);
while (read(fd[0],&number,sizeof(number)) > 0)
printf("The number is %d from child %d\n",number,getpid());
close(fd[0]);
}
return 0;
}
我得到的一个示例输出(在运行 macOS Big Sur 11.2.3 的 MacBook Pro 上运行)是:
write finished from parent process:53072
The number is 2 from child 53072
The number is 3 from child 53072
The number is 4 from child 53072
The number is 5 from child 53072
The number is 6 from child 53072
The number is 7 from child 53072
The number is 8 from child 53072
The number is 9 from child 53072
The number is 10 from child 53072
The number is 11 from child 53072
The number is 12 from child 53072
The number is 13 from child 53072
The number is 14 from child 53072
The number is 15 from child 53072
The number is 16 from child 53072
The number is 17 from child 53072
The number is 18 from child 53072
The number is 19 from child 53072
The number is 20 from child 53072
The number is 21 from child 53072
The number is 22 from child 53072
The number is 23 from child 53072
The number is 24 from child 53072
The number is 25 from child 53072
The number is 26 from child 53072
The number is 27 from child 53072
The number is 28 from child 53072
The number is 29 from child 53072
The number is 30 from child 53072
The number is 31 from child 53072
The number is 32 from child 53072
The number is 33 from child 53072
The number is 34 from child 53072
The number is 35 from child 53072
53069: child 53072 exited with status 0x0000
如果输出通过管道传输到另一个程序,“write finished from parent process:53072
”行出现在“退出”打印之前的末尾。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。