文章目录
- 一、管道
- 1.管道的特质
- 2.管道的用法——pipe函数
- 3.管道的读写行为
- 4..管道的优劣
- 二.实战练习:实现ls | wc -l 指令
- 三、fifo实现非血缘关系进程间通信
一、管道
1.管道的特质
-
实现原理:
内核借助环形队列机制,使用内核缓冲区实现。 -
特质:
1.伪文件
2.管道中的数据只能一次读取。
3.数据在管道中,只能单向流动。 -
局限性:
1.自己写,不能自己读。
2.数据不可以反复读。
3.半双工通信。
4.血缘关系进程间可用。
2.管道的用法——pipe函数
-
用处:
创建并打开管道 -
int pipe(int fd[2]);
-
参数:
fd[0]:读端
fd[1]:写端 -
返回值:
成功 0
失败:-1 error
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int ret;
int fd[2];
pid_t pid;
char *str = "hello pipe\n";
char buf[1024];
ret = pipe(fd);
if(ret == -1)
sys_err("pipe error");
pid = fork();
if(pid > 0){
close(fd[0]);
write(fd[1],str,strlen(str));
close(fd[1]);
}else if(pid == 0){
close(fd[1]);
ret = read(fd[0],buf,sizeof(buf));
write(STDOUT_FILENO,buf,ret);
close(fd[0]);
}
return 0;
}
3.管道的读写行为
读管道:
- 1.管道有数据,read返回实际读到的字节数。
- 2.管道无数据:
1)无写端,read返回0(类似读到文件尾)
2)有写端,read阻塞等待。
写管道:
- 1.无读端,异常终止。(SIGPIPE导致的)
- 2.有读端:
1)管道已满,阻塞等待
2)管道未满,返回写出的字节个数。
4…管道的优劣
- 优点:
简单,相比信号,套接字实现进程间通信,简单很多。 - 缺点:
1.只能单向通信,双向通信需建立两个管道。
2.只能用于歌子、兄弟进程(有共同祖先)间通信。该问题后来使用fifo有名管道解决。
二.实战练习:实现ls | wc -l 指令
- 该指令功能:
统计目录中的文件数 - 所需函数:
创建管道函数pipe();
创建子进程函数fork();
执行系统级函数(接管子进程函数)execlp();
重定向函数dup2();
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int fd[2];
int ret;
pid_t pid;
ret = pipe(fd);
if(ret == -1){
sys_err("pipe error");
}
pid = fork();
if(pid == -1){
sys_err("fork error");
}else if(pid > 0){ //父进程执行wc -l
close(fd[1]);
dup2(fd[0],STDIN_FIFLENO);
execlp("wc","wc","-l",NULL);
}else if(pid == 0){
close(fd[0]);
dup2(fd[1],STDOUT_FIFLENO);
execlp("ls","ls",NULL);
//不能用close,因为execlp走了就不回来了
}
return 0;
}
三、fifo实现非血缘关系进程间通信
先当于先创建管道文件
在对文件进行读写操作