- pipe函数
管道函数
man pipe
#include <unistd.h>
int pipe(int pipefd[2]);
参数介绍:
pipefd读写文件描述符,0-代表读, 1-代表写
父子进程实现pipe通信,实现ps aux | grep bash
功能
经常出现的问题:
父进程认为写端存在,就有可能还有人发送数据,继续等待
所以尽量保持管道数据的流向保持一致,所以先在子进程关闭读端,
父进程关闭写端,这样管道流向就是 子进程写,父进程读。
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
int fd[2];
pipe(fd);
pid_t pid = fork();
if(pid == 0) {
// son
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
execlp("ps", "ps", "aux", NULL);
} else if(pid>0){
// father
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("grep", "grep", "bash", NULL);
}
return 0;
}
- pipe管道的行为
读管道
a.写端全部关闭, -- read读到0,相当于读到文件末尾
b.写端没有全部关闭
b1.有数据 -- read读到数据
b2.没有数据 -- read阻塞 (fcntl函数可以更改为非阻塞)
写管道
a. 读端全部关闭, 产生一个信号,SIGPIPE(kill - 13),程序异常终止
b. 读端没有全部关闭
b1. 管道已满 --write阻塞
b2. 管道未满 --write正常写入,
- pipe 管道的大小
通过ulimit -a
pipe size (512 bytes, -p) 8
- pipe 管道缺点
只能单向通信, 双向通信需要建立两个管道
只有血缘关系的进程才能通信 - 兄弟进程实现
ps aux | grep bash
功能
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int fd[2];
pipe(fd);
pid_t pid;
int i=0, n=2;
for(i=0; i<n; i++) {
pid = fork();
if(pid == 0) {
break;
}
}
if(i == 0) {
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
execlp("ps", "ps", "aux", NULL);
} else if(i ==1 ) {
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("grep", "grep", "bash", NULL);
} else if(i == 2) {
close(fd[0]);
close(fd[1]);
wait(NULL);
wait(NULL);
}
return 0;
}