当read()阻塞时如何退出while循环
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当read()阻塞时如何退出while循环相关的知识,希望对你有一定的参考价值。
在大学给出的问题中,我们必须从父进程(P1)到其子P2的pipe
,然后P2必须管道到P1的另一个孩子,另一个孩子是P3。 P2和P3都用c编写并制成可执行文件。然后他们将通过P1中的子进程进行qazxswwied。
P1将数字1到10000写入exec
,P2通过其stdout
读取它们,删除可被2整除的数字,并将结果写入其stdin
。 P3通过其stdout
读取这些数字,过滤掉可被3整除的结果,并将所有内容写入文件。
我已经成功实现了一切,但我的孩子流程并没有结束。我相信,其原因是我使用以下方法来读取每个子进程中的输入:
stdin
根据我的理解,这里的问题是当while(n=read(0, &i, sizeof(i))>0)
没有得到任何字节时会阻塞。由于P1使用以下方法写入10000个数字:
read
儿童进程都没有任何理由相信没有更多的数据可以实现。因此,每个for(i=1; i<=10000; i++){
write(1, &i, sizeof(i));
}
只是阻止等待一个永远不会到来的字节。
任何人都可以建议一种方法来克服这个障碍吗?
每个过程的代码如下:
家长:
read
P2(包括除外)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
// pipe to send input string from parent
// Child prints to file
int fd1[2]; // Used to store two ends of first pipe
int fd2[2]; // Used to store two ends of second pipe
//variables
int n, i, status1, status2;
char *args1[]={"./Div2",NULL};
char *args2[]={"./Div3",NULL};
//child process ids
pid_t pid1, pid2;
//open pipe 1
if (pipe(fd1)==-1)
{
fprintf(stderr, "Pipe 1 Failed" );
return 1;
}
//open pipe 2
if (pipe(fd2)==-1)
{
fprintf(stderr, "Pipe 2 Failed" );
return 1;
}
//create child 1
pid1 = fork();
if(pid1<0){
printf("Error creating child1
");
return(1);
}
if(pid1==0){ //child1
if(close(fd1[1])<0){ //child does not write to pipe 1
error();
}
if(close(fd2[0])<0){ //child does not read from pipe 2
error();
}
dup2(fd1[0], 0); //redirect stdin
dup2(fd2[1], 1); //redirect stdout
execvp(args1[0],args1);
if(close(fd1[0])<0){ //close used pipe
error();
}
if(close(fd2[0])<0){ //close used pipe
error();
}
exit(0);
}
pid2=fork();
if(pid2<0){
printf("Error creating child2
");
return(1);
}
if(pid2==0){ //child2
if(close(fd1[0])<0){ //child does not use pipe 1
error();
}
if(close(fd1[1])<0){
error();
}
if(close(fd2[1])<0){ //child does not write to pipe 2
error();
}
dup2(fd2[0], 0); //redirect stdin
execvp(args2[0], args2);
if(close(fd2[0])<0){ //close pipe after use
error();
}
exit(0);
}
//parent
//parent doesn't read from the pipe
if(close(fd1[0])<0){
error();
}
if(close(fd2[0])<0){
error();
}
if(close(fd2[1])<0){
error();
}
dup2(fd1[1], 1); //redirect stdout
for(i=1; i<=10000; i++){
write(1, &i, sizeof(i));
}
if(close(fd1[1])<0){
error();
}
int returnedPID1=waitpid(pid1, &status1, 0);
if(returnedPID1==pid1){
printf("Parent waited for child as predicted
");
}
int returnedPID2=waitpid(pid2, &status2, 0);
if(returnedPID2==pid2){
printf("Parent waited for child as predicted
");
}
_exit(0);
}
PZ
int main()
{
int n;
int i;
while((n=read(0, &i, 4))>0){
if((i%2)!=0){
write(1, &i, sizeof(i));
}
}
return;
}
多谢你们。
除非出现错误,exec永远不会返回。所以当你写:
int main()
{
int n;
int i;
char tmp[12] = {0x0};
char *arg[]= {"/home/eric/Documents/pr3/test.txt"};
int fp = open(arg[0], O_WRONLY|O_CREAT|O_TRUNC, 0666);
if(fp<0){
printf("Error opening file
");
_exit(1);
}
while((n=read(0, &i, 4))>0){
if((i%3)!=0){
sprintf(tmp,"%11d", i);
write(fp, tmp, strlen(tmp));
}
}
return;
}
你希望关闭文件描述符是错误的。你执行前关闭它们。他们正在开放。虽然在你的特殊情况下问题是父节点永远不会关闭fd 1.父节点有两个文件描述符写入管道( execvp(args1[0],args1);
if(close(fd1[0])<0){ //close used pipe
error();
}
和fd[1]
),你需要在读取管道的子节点完成之前关闭它们。
以上是关于当read()阻塞时如何退出while循环的主要内容,如果未能解决你的问题,请参考以下文章