ls | wc -l 中的|就是运用了管道把两个命令之间连接起来,把前面一个命令运行的指令的结果通过管道传给后面那一个命令
有名/匿名管道共同的特点:
管道的两端分别对应了两个文件描述符
匿名管道一般用在有关系的进程间通信,有名管道一般用在没有关系的进程间的通信
单工:遥控器发射信号给电视机,电视机不能发射信号给遥控器
双工:两个人之间打电话是互相通的,同时可以听到互相的数据
半双工:同一个时间只能往一个方向,方向是两头都可以但同一时间只能进行一个
Q:为什么匿名管道只能用于有关系的进程通信?
A:
由于父子进程共享文件描述符所以可以用同一个管道进行通信。
管道的数据结构:环形队列
管道的使用函数:
/*
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建一个匿名管道,用来进程间通信。
参数:int pipefd[2] 这个数组是一个传出参数
pipe[0]对应的是管道的读端
pipe[1]对应的是管道的写端
返回值:
成功返回0,失败返回-1
管道默认是阻塞的:如果管道没有数据,read阻塞,如果管道满了,write阻塞
注意:匿名管道只能用于具有关系之间的进程通信,比如父子进程,兄弟进程
*/
//子进程发送数据给父进程,父进程读取到数据输出
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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());
//从管道的读取端读取数据
char buf[1024]={0};
while(1){
int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
printf("parent recv : %s, pid : %d\n",buf,getpid());
char *str="hello,i am parent";
write(pipefd[1],str,strlen(str));
sleep(1);
}
}else if(pid==0){
//子进程
printf("i am child process,pid : %d\n",getpid());
char buf[1024]={0};
while(1){
char *str="hello,i am child";
write(pipefd[1],str,strlen(str));
sleep(1);
int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
printf("child recv : %s, pid : %d\n",buf,getpid());
}
}
return 0;
}
这里用了sleep使得父子进程相互切换才做到了父子进程互相通信,一般管道通信不用sleep也一般是一个流向
/*
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建一个匿名管道,用来进程间通信。
参数:int pipefd[2] 这个数组是一个传出参数
pipe[0]对应的是管道的读端
pipe[1]对应的是管道的写端
返回值:
成功返回0,失败返回-1
管道默认是阻塞的:如果管道没有数据,read阻塞,如果管道满了,write阻塞
注意:匿名管道只能用于具有关系之间的进程通信,比如父子进程,兄弟进程
*/
//子进程发送数据给父进程,父进程读取到数据输出
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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());
//从管道的读取端读取数据
//关闭写端
close(pipefd[1]);
char buf[1024]={0};
while(1){
int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
printf("parent recv : %s, pid : %d\n",buf,getpid());
//char *str="hello,i am parent";
//write(pipefd[1],str,strlen(str));
//sleep(1);
}
}else if(pid==0){
//子进程
//关闭读端
close(pipefd[0]);
printf("i am child process,pid : %d\n",getpid());
char buf[1024]={0};
while(1){
char *str="hello,i am child\n";
write(pipefd[1],str,strlen(str));
//sleep(1);
// int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
// printf("child recv : %s, pid : %d\n",buf,getpid());
// bzero(buf,1024);
}
}
return 0;
}
pipe size = 512 * 8 = 4k
可以用ulimit -p 修改
/*
#include <unistd.h>
long fpathconf(int fd, int name);
*/
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int pipefd[2];
int ret=pipe(pipefd);
long size=fpathconf(pipefd[0],_PC_PIPE_BUF);//获取管道的大小
printf("pipe size : %ld\n",size);
return 0;
}