匿名管道的非阻塞读写特性
注意:以下都是非阻塞状态下的匿名管道的读写特性
读设置为非阻塞
(1) 写不关闭,一直读,读端调用read函数之后,返回值为-1(-1的原因有两个:一是管道当中没有内容,没读到,二是读错了),errno置为EAGAIN则为没读到内容(2) 写关闭,一直读,读端read函数返回0,表示什么都没有读到
写设置为非阻塞
(1) 读不关闭,一直写,当把管道写满之后,则在调用write,就会返回-1
(2) 读关闭,一直写,写端调用write进行写的时候,就会发生崩溃。本质上是写端的进程收到了SIGPIPE(13)信号,导致了写端的进程崩溃
非阻塞读,写不关闭
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* arg[]){
int fd[2];
int ret = pipe(fd);
if(ret < 0){
perror("pipe");
return 0;
}
//设置管道读端为非阻塞
int flag = fcntl(fd[0], F_GETFL);
fcntl(fd[0], F_SETFL, flag | O_NONBLOCK);
pid_t pid = fork();
if(pid < 0){
perror("fork");
return 0;
}else if(pid == 0){
//child
//fd[0], fd[1]
//人为规定,子进程来读
//read -> fd[0] => 非阻塞(需要搭配循环来使用)
char buf[1024] = {0};
size_t read_size = read(fd[0], buf, sizeof(buf) - 1);
printf("read_size:%ld\n", read_size);
}else{
//father
//fd[0], fd[1]
//人为规定:父进程来写,write
//write -> fd[1]
//对于父进程有两种情况:写关闭和写不关闭
//1.写不关闭
close(fd[0]);//读关闭
}
return 0;
}
非阻塞读,写关闭
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* arg[]){
int fd[2];
int ret = pipe(fd);
if(ret < 0){
perror("pipe");
return 0;
}
//设置管道读端为非阻塞
int flag = fcntl(fd[0], F_GETFL);
fcntl(fd[0], F_SETFL, flag | O_NONBLOCK);
pid_t pid = fork();
if(pid < 0){
perror("fork");
return 0;
}else if(pid == 0){
//child
//fd[0], fd[1]
//人为规定,子进程来读
//read -> fd[0] => 非阻塞(需要搭配循环来使用)
//关闭写端
close(fd[1]);
char buf[1024] = {0};
size_t read_size = read(fd[0], buf, sizeof(buf) - 1);
printf("read_size:%ld\n", read_size);
}else{
//father
//fd[0], fd[1]
//人为规定:父进程来写,write
//write -> fd[1]
//对于父进程有两种情况:写关闭和写不关闭
//2.写关闭
close(fd[1]);
close(fd[0]);//读关闭
}
return 0;
}
非阻塞写,读不关闭
写一次
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* arg[]){
int fd[2];
int ret = pipe(fd);
if(ret < 0){
perror("pipe");
return 0;
}
//设置管道写端为非阻塞
int flag = fcntl(fd[1], F_GETFL);
fcntl(fd[1], F_SETFL, flag | O_NONBLOCK);
pid_t pid = fork();
if(pid < 0){
perror("fork");
return 0;
}else if(pid == 0){
//child
//fd[0], fd[1]
//人为规定,子进程来写
//write -> fd[1] => 非阻塞(需要搭配循环来使用)
size_t write_size = write(fd[1], "I am hacker~", 13);
printf("write_size:%ld\n", write_size);
}else{
//father
//fd[0], fd[1]
//人为规定:父进程来读
//read -> fd[0]
//对于父进程有两种情况:读关闭和读不关闭
//1.写关闭
close(fd[1]);
//读不关闭
//close(fd[0]);
}
return 0;
}
一直写
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* arg[]){
int fd[2];
int ret = pipe(fd);
if(ret < 0){
perror("pipe");
return 0;
}
//设置管道写端为非阻塞
int flag = fcntl(fd[1], F_GETFL);
fcntl(fd[1], F_SETFL, flag | O_NONBLOCK);
pid_t pid = fork();
if(pid < 0){
perror("fork");
return 0;
}else if(pid == 0){
//child
//fd[0], fd[1]
//人为规定,子进程来写
//write -> fd[1] => 非阻塞(需要搭配循环来使用)
close(fd[0]);
int count = 0;
while(1){
size_t write_size = write(fd[1], "i", 1);
if(write_size != 1){
printf("write_size:%ld\n", write_size);
break;
}
printf("count:%d\n", ++count);
}
}else{
//father
//fd[0], fd[1]
//人为规定:父进程来读
//read -> fd[0]
//对于父进程有两种情况:读关闭和读不关闭
//1.写关闭
close(fd[1]);
//读不关闭
//close(fd[0]);
//防止父进程退出,父进程退出会导致所有读端关闭(读端只有父进程一个在开启着,所以父进程退出了就没有读端了)
while(1){};
}
return 0;
}
非阻塞写,读关闭
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* arg[]){
int fd[2];
int ret = pipe(fd);
if(ret < 0){
perror("pipe");
return 0;
}
//设置管道写端为非阻塞
int flag = fcntl(fd[1], F_GETFL);
fcntl(fd[1], F_SETFL, flag | O_NONBLOCK);
pid_t pid = fork();
if(pid < 0){
perror("fork");
return 0;
}else if(pid == 0){
//child
//fd[0], fd[1]
//人为规定,子进程来写
//write -> fd[1] => 非阻塞(需要搭配循环来使用)
printf("I am child\n");
close(fd[0]);
int count = 0;
while(1){
size_t write_size = write(fd[1], "i", 1);
if(write_size != 1){
printf("write_size:%ld\n", write_size);
break;
}
printf("count:%d\n", ++count);
}
}else{
//father
//fd[0], fd[1]
//人为规定:父进程来读
//read -> fd[0]
//对于父进程有两种情况:读关闭和读不关闭
//1.写关闭
close(fd[1]);
//读关闭
close(fd[0]);
//保留父进程,方便观察子进程状态
while(1){};
}
return 0;
}