#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;
}