Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在read()阻塞时退出while循环_C_Linux_Pipe - Fatal编程技术网

C 如何在read()阻塞时退出while循环

C 如何在read()阻塞时退出while循环,c,linux,pipe,C,Linux,Pipe,在大学给出的一个问题中,我们必须从父进程(P1)到其子进程P2,然后P2必须通过管道到P1的另一个子进程,另一个子进程是P3。P2和P3都将用c编写,并制作成可执行文件。然后,它们将由P1中的子进程执行 P1将数字1到10000写入stdout,P2通过其stdin读取它们,删除可被2整除的数字,并将结果写入其stdout。P3通过其stdin读取这些数字,过滤出可被3整除的结果,并将所有内容写入文件 我已经成功地实现了一切,但我的子进程并没有结束。我认为,这是因为我使用了以下方法来读取每个孩子

在大学给出的一个问题中,我们必须
从父进程(P1)到其子进程P2,然后P2必须通过管道到P1的另一个子进程,另一个子进程是P3。P2和P3都将用c编写,并制作成可执行文件。然后,它们将由P1中的子进程执行

P1将数字1到10000写入
stdout
,P2通过其
stdin
读取它们,删除可被2整除的数字,并将结果写入其
stdout
。P3通过其
stdin
读取这些数字,过滤出可被3整除的结果,并将所有内容写入文件

我已经成功地实现了一切,但我的子进程并没有结束。我认为,这是因为我使用了以下方法来读取每个孩子的输入:

while(n=read(0, &i, sizeof(i))>0)
据我所知,这里的问题是
read
在没有任何字节时会阻塞。当P1写入10000个数字时,使用:

for(i=1; i<=10000; i++){
        write(1, &i, sizeof(i));
    }
P2(包括不包括在内)

P3

intmain()
{
int n;
int i;
char tmp[12]={0x0};
char*arg[]={/home/eric/Documents/pr3/test.txt“};
int fp=open(arg[0],O_WRONLY | O|u CREAT | O|u TRUNC,0666);
如果(fp0){
如果((i%3)!=0){
sprintf(tmp,“%11d”,i);
写入(fp、tmp、strlen(tmp));
}   
}
回来
}

谢谢各位。

除非出现错误,否则exec永远不会返回。所以当你写作时:

    execvp(args1[0],args1);
    if(close(fd1[0])<0){ //close used pipe
        error();
    }
execvp(args1[0],args1);

如果(close(fd1[0]),除非出现错误,否则exec永远不会返回。因此,当您写入时:

    execvp(args1[0],args1);
    if(close(fd1[0])<0){ //close used pipe
        error();
    }
execvp(args1[0],args1);

如果以(close(fd1[0])开头,
n=read(…)>0
显然不会像您预期的那样工作,因为它等于
n=(read(…)>0)
。也就是说,它将比较结果分配给
n
。至于在
read
阻塞时中断循环,这是不可能的,因为您被困在
read
调用中。但是,您可以轮询描述符,查看调用
read
是否会阻塞。一种方法是使用调用。
while(n=read(0,&i,sizeof(i))>0)
-->
while((n=read(0,&i,sizeof(i))>0)
当管道的所有写入程序都关闭时,第一次尝试
read
时,EOF将返回0。任何未来的
read
s都会导致SIGPIPE,默认情况下会终止进程;如果失败,
read
返回并将
errno
设置为
EPIPE
。如果
read
阻塞,则意味着某些写入er仍处于打开状态。有关详细信息,请参阅。读取永远不会导致SIGPIPE。后续读取将立即返回0(或-1)。只有写入操作才能生成SIGPIPE。首先,
n=read(…)>0
不会像您预期的那样工作,因为它等于
n=(read(…)>0)
。也就是说,它将比较结果分配给
n
。至于在
read
阻塞时中断循环,这是不可能的,因为您被困在
read
调用中。但是,您可以轮询描述符,查看调用
read
是否会阻塞。一种方法是使用调用。
while(n=read(0,&i,sizeof(i))>0)
-->
while((n=read(0,&i,sizeof(i))>0)
当管道的所有写入程序都关闭时,第一次尝试
read
时,EOF将返回0。任何未来的
read
s都会导致SIGPIPE,默认情况下会终止进程;如果失败,
read
返回并将
errno
设置为
EPIPE
。如果
read
阻塞,则意味着某些写入er仍处于打开状态。有关详细信息,请参阅。读取将不会导致SIGPIPE。后续读取将立即返回0(或-1)。只有写入操作才能生成SIGPIPE。“exec从不返回。”-->“…通常不返回,…如果发生故障,将返回值-1。”“exec从不返回。”-->“…通常不返回,…如果发生故障,将返回值-1。”
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\n");
            _exit(1);
        }

    while((n=read(0, &i, 4))>0){
        if((i%3)!=0){
            sprintf(tmp,"%11d", i);
            write(fp, tmp, strlen(tmp));
        }   
    }
    return;
}
    execvp(args1[0],args1);
    if(close(fd1[0])<0){ //close used pipe
        error();
    }