パイプラインの読み取りと書き込みの特性は次のとおりです。
パイプを使用する場合は、注意する必要があります (デフォルトでは I/O 操作がブロックされます)。
1. パイプの書き込み端を指すすべてのファイル記述子が閉じられ (パイプの書き込み端の参照カウントは 0)、パイプの読み取り端からデータを読み取るプロセスであり、パイプの残りのデータが読み取られた後、
再度読み取りを行うと、ファイルの最後まで読み取るのと同様に 0 が返されます。
2. パイプの書き込み端を指すファイル記述子が閉じられておらず (パイプの書き込み端の参照カウントが 0 より大きい)、パイプの書き込み端を保持しているプロセスがパイプにデータを書き込まない場合、このとき、パイプからデータを読み取るプロセスが存在します。
その後、パイプ内の残りのデータが読み取られた後、読み取りは再びブロックされます。パイプ内に読み取り可能なデータが存在するまで、データは読み取られず、返されません。
3. パイプの読み取り端を指すすべてのファイル記述子が閉じられており (パイプの読み取り端参照カウントが 0 である)、この時点でプロセスがパイプにデータを書き込む場合、プロセスはシグナル SIGPIPE を受け取ります。通常、これによりプロセス例外が発生します。
4. パイプの読み取り端を指すファイル記述子がクローズされていない場合 (パイプの読み取り端の参照カウントが 0 より大きい)、パイプの読み取り端を保持しているプロセスがファイル記述子からデータを読み取りません。パイプにデータを書き込み、プロセスがパイプにデータを書き込む
と、パイプがいっぱいになると、パイプ内に空の位置ができるまで再度書き込みがブロックされ、その後データが再度書き込まれて返されます。
読み取りパイプラインの概要
:
パイプ内にデータがあり、読み取りは実際に読み取られたバイト数を返します。
パイプ内にデータはありません:
書き込み端は完全に閉じられており、読み取りは 0 を返します (ファイルの終わりを読み取るのと同等) 、
書き込み端が完全に閉じられていないため、読み取りがブロックされ、
書き込みを待機します。 パイプ:
すべてのパイプ読み取り端が閉じられ、プロセスが異常終了します (プロセスは SIGPIPE シグナルを受信します)。パイプ
読み取り端はすべて閉じられていません
:パイプがいっぱいである場合、ブロックを書き込みます、
パイプがいっぱいではない場合、write はデータを書き込み、実際に書き込まれたバイトを返します。
パイプをブロックしないように設定します
//子进程发送数据给父进程,父进程读取到数据输出
#include <unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
/*
设置管道非阻塞
fcntl(fd[0], F_GETFL) //获取原来的flag
flags |= O_NONBLOCK //修改flag
fcntl(fd[0], F_SETFL, flags); //设置新的flag
*/
int main() {
//在fork之前创建管道
int pipefd[2];
int ret = pipe(pipefd);
if(ret == -1) {
perror("pipe");
exit(0);
}
//创建子进程
pid_t pid = fork();
if(pid > 0) {
//父进程
//从管道读取端读取数据
printf("i am parent process, pid: %d\n", getpid());
int flags = fcntl(pipefd[0], F_GETFL);
flags |= O_NONBLOCK;
fcntl(pipefd[0], F_SETFL, flags);
//关闭写端
close(pipefd[1]);
char buf[1024] = {0};
while(1) {
//在管道中读取数据
int len = read(pipefd[0], buf, sizeof(buf));
printf("len : %d\n", len);
printf("parent recv : %s, pid: %d\n", buf, getpid());
memset(buf, 0, 1024);
sleep(1);
}
} else if(pid == 0){
//子进程
printf("i am child process, pid: %d\n", getpid());
//关闭读端
close(pipefd[0]);
char buf[1024] = {0};
while(1) {
//在管道中写入数据
char * str = "hello, i am child";
write(pipefd[1], str, strlen(str));
sleep(5);
}
}
return 0;
}