1. 当没有数据可读时
O_NONBLOCK disable
:
read
调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable
:
read
调用返回
-1
,
errno
值为
EAGAIN
。
2. 当管道满的时候
O_NONBLOCK disable:
write
调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回
-1
,
errno
值为
EAGAIN
3 如果所有管道写端对应的文件描述符被关闭,则
read
返回
0
4 如果所有管道读端对应的文件描述符被关闭,则
write
操作会产生信号
SIGPIPE,
进而可能导致
write进程退出
5 当要写入的数据量不大于
PIPE_BUF
时,
linux
将保证写入的原子性。
6 当要写入的数据量大于
PIPE_BUF
时,
linux
将不再保证写入的原子性。
当读端打开,而写端不写入任何数据,这是就会出现堵塞
int main()
{
int pipe_fd[2];
int r_size = 0;
pid_t child_pid;
if (pipe(pipe_fd) == -1)
{
perror("pipe error:");
return -1;
}
//那么这里pipe就会打开2个文件描述符pipe_fd[0]表示读端
child_pid = fork();
if (child_pid == 0)//读
{
//子进程也继承了2个文件描述符
close(pipe_fd[1]);//子进程读端我们会关闭写端
char recv_buffer[50];
memset(recv_buffer, 0, sizeof(recv_buffer));
cout << "child ready read..." << endl;
read(pipe_fd[0], recv_buffer, sizeof(recv_buffer));//希望读到buffer的所有字节
cout << "child recv buffer=" << recv_buffer << endl;
while (1)
{
sleep(1);//不让子进程结束
}
}
else if (child_pid > 0)//写
{
close(pipe_fd[0]);//父进程写端我们会关闭读端
char buffer[50] = { 0 };
strcpy(buffer, "hello rabbit!");
//如果发送的是字符串那么可以使用strlen函数
//r_size = write(pipe_fd[1], buffer, strlen(buffer));
while (1)
{
sleep(1);//不让父进程结束
}
}
return 0;
}
这时我们运行代码出现结果如下
这是我们会发现子进程就发生堵塞
当写端一直在写入,而读端不读取数据
int main()
{
int pipe_fd[2];
int r_size = 0;
pid_t child_pid;
if (pipe(pipe_fd) == -1)
{
perror("pipe error:");
return -1;
}
//那么这里pipe就会打开2个文件描述符pipe_fd[0]表示读端
child_pid = fork();
if (child_pid == 0)//读
{
//子进程也继承了2个文件描述符
close(pipe_fd[1]);//子进程读端我们会关闭写端
char recv_buffer[50];
memset(recv_buffer, 0, sizeof(recv_buffer));
//cout << "child ready read..." << endl;
//read(pipe_fd[0], recv_buffer, sizeof(recv_buffer));//希望读到buffer的所有字节
//cout << "child recv buffer=" << recv_buffer << endl;
while (1)
{
sleep(1);//不让子进程结束
}
}
else if (child_pid > 0)//写
{
close(pipe_fd[0]);//父进程写端我们会关闭读端
char buffer[50] = { 0 };
strcpy(buffer, "h");
//如果发送的是字符串那么可以使用strlen函数
//r_size = write(pipe_fd[1], buffer, strlen(buffer));
int size=0;
while (1)
{
r_size = write(pipe_fd[1], buffer, strlen(buffer));
//sleep(1);//不让父进程结束
size+=strlen(buffer);
cout<<size<<endl;
}
}
return 0;
}
运行之后的结果如下
可知管道最大可以存储65536个字节,当管道存储达到上限值之后,而读端,不读取,就会发生堵塞
当读端正常运行,写端突然关闭
int main()
{
int pipe_fd[2];
int r_size = 0;
pid_t child_pid;
if (pipe(pipe_fd) == -1)
{
perror("pipe error:");
return -1;
}
//那么这里pipe就会打开2个文件描述符pipe_fd[0]表示读端
child_pid = fork();
if (child_pid == 0)//读
{
//子进程也继承了2个文件描述符
//close(pipe_fd[1]);//子进程读端我们会关闭写端
//char recv_buffer[50];
//memset(recv_buffer, 0, sizeof(recv_buffer));
//cout << "child ready read..." << endl;
//ssize_t n=read(pipe_fd[0], recv_buffer, sizeof(recv_buffer));//希望读到buffer的所有字节
//cout << "child recv buffer=" << recv_buffer << endl;
while (1)
{
//sleep(1);//不让子进程结束
//close(pipe_fd[1]);//子进程读端我们会关闭写端
char recv_buffer[50];
memset(recv_buffer, 0, sizeof(recv_buffer));
cout << "child ready read..." << endl;
ssize_t n=read(pipe_fd[0], recv_buffer, sizeof(recv_buffer));//希望读到buffer的所有字节
cout << "child recv buffer=" << recv_buffer << endl;
cout<<n<<endl;
}
}
else if (child_pid > 0)//写
{
close(pipe_fd[0]);//父进程写端我们会关闭读端
char buffer[50] = { 0 };
strcpy(buffer, "h");
//如果发送的是字符串那么可以使用strlen函数
r_size = write(pipe_fd[1], buffer, strlen(buffer));
close(pipe_fd[1]);
while (1)
{
sleep(1);//不让父进程结束
}
}
return 0;
}
运行结果如下
依然是堵塞状态,不会出现任何的错误,读端会返回0;
当我们的写端写入,读端突然退出
int main()
{
int pipe_fd[2];
int r_size = 0;
pid_t child_pid;
if (pipe(pipe_fd) == -1)
{
perror("pipe error:");
return -1;
}
//那么这里pipe就会打开2个文件描述符pipe_fd[0]表示读端
child_pid = fork();
if (child_pid == 0)//读
{
//子进程也继承了2个文件描述符
close(pipe_fd[1]);//子进程读端我们会关闭写端
char recv_buffer[50];
memset(recv_buffer, 0, sizeof(recv_buffer));
cout << "child ready read..." << endl;
ssize_t n=read(pipe_fd[0], recv_buffer, sizeof(recv_buffer));//希望读到buffer的所有字节
cout << "child recv buffer=" << recv_buffer << endl;
close(pipe_fd[0]);
while (1)
{
sleep(1);//不让子进程结束
}
}
else if (child_pid > 0)//写
{
close(pipe_fd[0]);//父进程写端我们会关闭读端
char buffer[50] = { 0 };
strcpy(buffer, "h");
//如果发送的是字符串那么可以使用strlen函数
//r_size = write(pipe_fd[1], buffer, strlen(buffer));
while (1)
{
r_size = write(pipe_fd[1], buffer, strlen(buffer));
//sleep(1);//不让父进程结束
}
}
return 0;
}
这是运行会报错(如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出);