#include <unistd.h>
int pipe(int filedes[2]);
参数:输出型参数,调用pipe函数时在内核中开辟一块缓冲区(称为管道文件)用于通信,它有一个读端一个写端,然后通过filedes参数传出两个文件描述符,filedes[0]=3指向管道的读端,filedes[1]=4指向管道的写端。
返回值:pipe函数调用成功返回0,调用失败返回-1。
匿名管道在通信中有以下特点:
1.两个进程只能实现单向通信;
2.只有血缘关系的进程才可以通信;(此特点是其与命名管道唯一的区别)
3.管道的生命周期随进程的结束而结束;
4.管道通信的传输为面向字节流;
5.匿名管道自带同步机制。
实现机制如下:
在此处代码实现中第三步骤则改为父进程关闭fd[1]负责读,子进程关闭fd[0]负责写:
#include <stdio.h>
#include <unistd.h>
int main()
{
int fd[2];
if(pipe(fd)<0) //打开匿名管道
{
perror("pipe");
return -1;
}
else //成功
{
int id=fork(); //创建子进程
if(id==0) //child write
{
close(fd[0]); //关闭管道文件读端
char buf[1024];
while(1)
{
//从标准输入(键盘)输入消息
printf("Please Enter#");
fflush(stdout);
//读到buf中
ssize_t s=read(0,buf,sizeof(buf));
if(s>0)
{
buf[s-1]=0;
}
//从buf中写入管道文件中
sleep(1);
write(fd[1],buf,sizeof(buf));
sleep(1);
}
}
else //father read
{
close(fd[1]); //关闭管道文件写端
char buf[1024];
while(1)
{
buf[0]=0;
ssize_t s=read(fd[0],buf,sizeof(buf)); //父进程从管道文件中读取消息
if(s>0)
{
buf[s-1]=0;
printf("%s\n",buf);
}
}
}
}
return 0;
}
效果如下:
在管道实现中会出现以下四种情况(以代码实现为例):
1.父进程若不读且并不关闭fd[0],则子进程写满管道后会自行阻塞等待直至父进程来读取(由此可测出管道容量,如下一个代码就以此为原理实现);
2.子进程若不写且并不关闭fd[1],则父进程不读会阻塞等待直至子进程来写;
3.父进程若不读并关闭了fd[0],则操作系统会关闭在写的子进程;
4.子进程若不写并关闭了fd[1],则父进程相当于读一个文件,当文件读完则退出,返回0值。
以下则以上面第一种情况为例测出管道的容量:
#include <stdio.h>
#include <unistd.h>
void CapacityOfPipe()
{
int fd[2];
pipe(fd); //打开管道文件
//定义初始化buf大小为4K
char buf[4096];
int i=0;
for(;i<sizeof(buf);++i)
{
buf[i]='1';
}
i=0;
for(;i<100;++i)
{
//每次向管道文件写入4K大小,最后若阻塞则最后一次大小为管道总容量
ssize_t s=write(fd[1],buf,sizeof(buf));
if(s<0)
{
perror("write");
}
else
{
printf("%d ",s);
printf("Capacity## %d*4K=%dk\n",i,i*4);
}
}
//关闭管道文件
close(fd[0]);
close(fd[1]);
}
int main()
{
CapacityOfPipe();
return 0;
}
结果如下:
可知在第15次以后管道已满开始阻塞等待,此时的容量大小为60kb,即可得出我的linux系统下管道容量为64kb.
命名管道(FIFO)的实现:
其与匿名管道区别:与血缘关系无关,可以让相互无关的进程进行通信。
代码实现:实质为读写一份共同管道文件。
server.c:(读)
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
umask(0);
if(mkfifo("PipeFile",S_IFIFO|0666)<0)
{
perror("mkfifo");
return -1;
}
else
{
int fd=open("PipeFile",O_RDONLY);
char buf[1024];
while(1)
{
buf[0]=0;
ssize_t s=read(fd,buf,sizeof(buf));
if(s<=0)
{
perror("read");
return -2;
}
else
{
buf[s-1]=0;
printf("%s\n",buf);
}
}
close(fd);
}
return 0;
}
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int fd=open("PipeFile",O_WRONLY);
char buf[1024];
while(1)
{
printf("Please Enter#");
fflush(stdout);
ssize_t s=read(0,buf,sizeof(buf));
if(s<0)
{
perror("read");
return -1;
}
else
{
buf[s-1]=0;
write(fd,buf,sizeof(buf));
}
}
close(fd);
return 0;
}