无名管道:
无名管道的特点:
只能用于具有亲缘关系间的通信。【父子进程 或 兄弟进程】
半双工通信。【只能由一方发送,另一方接收】
通信端口固定。【fd[0]:读管道 ,fd[1]:写管道】
管道也是一种特殊的文件,对于它的读写,也可以使用普通的read(),write()函数。
管道不属于任何文件系统,只存在于内存中。
无名管道的创建
无名管道的相关函数
头文件:#include<unistd.h>
函数名:pipe
参数:int pipefd[] :包含两个元素的整型数组,存
放管道对应的文件描述符
返回值:成功--> 0 失败--> -1
int pipe(int pipefd[]);
pipe函数创建的管道两端处于同一个进程中。由于管道主要是用于不同进程间的通信,所以首先会fork()一个子进程,该子进程会继承父进程所创建的管道。此时父子进程就都拥有了一个管道,所以会产生两个fd[0],fd[1]。
根据需要,若是父进程发消息,子进程收消息。那么久关闭父进程的fd[1],关闭子进程的fd[0]。此时父进程就只有fd[0],子进程也就只有fd[1]了。他们俩就能通过无名管道来进行单向通信。
同理,若是需要子进程发送数据,父进程接收数据,就关闭对应的文件描述符即可。
举个栗子
注意事项:
只有管道的读端存在时,向管道内写入数据才有意义。否则,向管道内写入的数据的进程会收到内核传来的SIGPIPE信号。【通常为Broken Pipe(管道破裂) 错误】
向管道内写入数据时,Linux不保证写入的原子性,管道缓冲区只要有空间,写进程就会向管道写入数据;若管道已满,则写操作会阻塞等待
父子进程在运行时,他们的先后次序不能保证。 为确保父子进程已经关闭了相应的文件描述符,可以在两个进程中调用 sleep()函数
【附】上述例子的源码:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
int main(void)
{
pid_t pid = -1;
int pipefd[2];
//创建无名管道
if(0 > pipe(pipefd))
{
perror("pipe error!\n");
return -1;
}
puts("pipe success!");
/*pipe[0]读端 , pipe[1]写端*/
pid = fork();//创建子进程
//判断是否创建成功
if(0 > pid)//pid错误
{
perror("fork error!\n");
return -1;
}
else if(0 < pid)
{
//父进程 发 子进程 收
close(pipefd[0]);//关闭父进程的读端fd[0]
//发送数据
char buf[20] = {0};
//从键盘输入小于20的字符串
gets(buf , sizeof(buf) , stdin);
//将获得的字符串通过管道传递给子进程(pipefd[1]是子进程的接收端)
write(pipefd[1] , buf , strlen(buf));
//关闭父进程的写文件描述符
close(pipefd[1]);
}
else if(0 == pid)
{
//子进程
close(pipefd[1]);//关闭子进程的写端fd[1]
//接收数据
char buf1[20] = {0};
read(pipefd[0] , buf1 , sizeof(buf1));
printf("read data : %s\n" , buf1);
//关闭读端
close(pipefd[0]);
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//-----------------------------------------------示例二--------------------------------------------//
int main()
{
int fd[2];
int pid;
char readbuf[128];
if(pipe(fd) == -1){
printf("creat pipe fail\n");
}
pid = fork();
if(pid < 0){
printf("creat child fail\n");
}
else if(pid > 0){
printf("this is father\n");
sleep(3);
close(fd[0]);
write(fd[1],"hellow this father",strlen("hellow this father"));
wait();
}else{
printf("this is child\n");
close(fd[1]);
read(fd[0],readbuf,128);
printf("this is from father:%s\n",readbuf);
exit(0);
}
return 0;
}