要保證是對(duì)同一個(gè)管道進(jìn)行操作瞄桨。
1孩饼、管道
管道文件是一個(gè)特殊的文件说榆,就是一個(gè)緩沖伶椿,是由隊(duì)列來(lái)實(shí)現(xiàn)的研乒,出隊(duì)端讀阱缓,入隊(duì)端寫(xiě)古掏。
在文件IO中創(chuàng)建一個(gè)文件或打開(kāi)一個(gè)文件是由open函數(shù)來(lái)實(shí)現(xiàn)的帜平,但它不能創(chuàng)建管道文件吟温,只能用pipe函數(shù)來(lái)創(chuàng)建管道序仙。
函數(shù)形式:
int pipe(int fd[2])
功能:創(chuàng)建管道,為系統(tǒng)調(diào)用:unistd.h(系統(tǒng)調(diào)用函數(shù)所在的.h文件)
參數(shù):就是得到的文件描述符鲁豪∨说浚可見(jiàn)有兩個(gè)文件描述符:fd[0]和fd[1],管道有一個(gè)讀端fd[0]用來(lái)讀和一個(gè)寫(xiě)端fd[1]用來(lái)寫(xiě)爬橡,這個(gè)規(guī)定不能變治唤。
返回值:成功是0,出錯(cuò)是-1糙申;
例1:pipe函數(shù)的使用
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
int fd[2];
int ret;
ret = pipe(fd);
if(ret < 0)
{
printf("create pipe fail\n");
return -1;
}
printf("create pipe success fd[0]=%d, fd[1]=%d\n",fd[0],fd[1]);
return 0;
}
解釋?zhuān)簅pen函數(shù)如果創(chuàng)建成功肝劲,返回的文件描述符從3開(kāi)始。
因?yàn)橐粋€(gè)進(jìn)程打開(kāi)時(shí)郭宝,內(nèi)核會(huì)自動(dòng)打開(kāi)3個(gè)文件描述符:0辞槐、1、2粘室。
例2:pipe函數(shù)的使用
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
int fd[2];
int ret;
char writebuf[] = "hello linux";
char readbuf[128] = {0};
ret = pipe(fd);
if(ret < 0)
{
printf("create pipe fail\n");
return -1;
}
printf("create pipe success fd[0]=%d, fd[1]=%d\n",fd[0],fd[1]);
write(fd[1], writebuf, sizeof(writebuf));
// start read from pipe
read(fd[0], readbuf, 128);
printf("readbuf = %s\n", readbuf);
close(fd[0]);
close(fd[1]);
return 0;
}
2榄檬、管道特點(diǎn)
- 管道是創(chuàng)建在內(nèi)存中的;進(jìn)程結(jié)束衔统,空間釋放鹿榜,管道就不存在了。
- 管道中的東西锦爵,讀完了就刪除了(和隊(duì)列是一樣的)
- 如果管道中沒(méi)有東西可讀舱殿,則會(huì)讀阻塞。
例3:驗(yàn)證讀阻塞
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
int fd[2];
int ret;
char writebuf[] = "hello linux";
char readbuf[128] = {0};
ret = pipe(fd);
if(ret < 0)
{
printf("create pipe fail\n");
return -1;
}
printf("create pipe success fd[0]=%d, fd[1]=%d\n",fd[0],fd[1]);
write(fd[1], writebuf, sizeof(writebuf));
// start read from pipe
read(fd[0], readbuf, 128);
printf("readbuf = %s\n", readbuf);
// second read from pipe
memset(readbuf, 0, 128);
read(fd[0], readbuf, 128);
printf("second read complete\n");
close(fd[0]);
close(fd[1]);
return 0;
}
例4:驗(yàn)證會(huì)寫(xiě)阻塞
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
int fd[2];
int ret;
int i = 0;
char writebuf[] = "hello linux";
char readbuf[128] = {0};
ret = pipe(fd);
if(ret < 0)
{
printf("create pipe fail\n");
return -1;
}
printf("create pipe success fd[0]=%d, fd[1]=%d\n",fd[0],fd[1]);
while(i < 5500)
{
write(fd[1], writebuf, sizeof(writebuf));
i++;
}
printf("write pipe end\n"); // 如果存在寫(xiě)阻塞樟氢,這句話不會(huì)被打印出來(lái)
close(fd[0]);
close(fd[1]);
return 0;
}
例5:驗(yàn)證寫(xiě)阻塞:可以計(jì)算出內(nèi)核開(kāi)辟的管道有多大侠鳄。
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
int fd[2];
int ret;
int i = 0;
char writebuf[] = "hello linux";
char readbuf[128] = {0};
ret = pipe(fd);
if(ret < 0)
{
printf("create pipe fail\n");
return -1;
}
printf("create pipe success fd[0]=%d, fd[1]=%d\n",fd[0],fd[1]);
while(i < 5400)
{
write(fd[1], writebuf, sizeof(writebuf));
i++;
}
printf("write pipe end\n"); // 如果存在寫(xiě)阻塞,這句話不會(huì)被打印出來(lái)
close(fd[0]);
close(fd[1]);
return 0;
}
范圍:5456-5457之間伟恶。即:5456是非阻塞,5457是阻塞毅该。
例6:通過(guò)管道實(shí)現(xiàn)進(jìn)程間通信
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
int main()
{
pid_t pid;
int fd[2]; // 文件描述符數(shù)組
int ret; // 返回值
int process_inter = 0;
// pipe必須放在子進(jìn)程之前(pipe函數(shù)必須在fork函數(shù)之前)博秫。這樣才是同一個(gè)管道。
ret = pipe(fd);
if(fd<0)
{
printf("create pipe fail\n");
return -1;
}
printf("create pipe success\n");
pid = fork();
if(pid == 0) // child process
{
int i = 0;
read(fd[0], &process_inter, 1); // child process read
while(process_inter == 0); // 如果讀到是0眶掌,一直循環(huán)
for(i = 0; i < 5; i++) // 如果讀到是1挡育,就往下運(yùn)行
{
printf("this is child process %d\n", i);
usleep(100);
}
}
if(pid>0) // parent process
{
int i = 0;
for(i=0;i<5;i++)
{
printf("this is parent process i=%d\n", i);
usleep(100);
}
process_inter = 1;
sleep(5); // 父進(jìn)程運(yùn)行完后,休眠5s
write(fd[1], &process_inter, 1); // parent process write
}
while(1);
return 0;
}
3良价、無(wú)名管道的缺點(diǎn)
只能實(shí)現(xiàn)父子關(guān)系或者有親緣關(guān)系的進(jìn)程間的通信寝殴。
因?yàn)榉歉缸雨P(guān)系的進(jìn)程,在pipe函數(shù)創(chuàng)建無(wú)名管道時(shí)明垢,都會(huì)各自創(chuàng)建一個(gè)管道蚣常,它們只能與各自創(chuàng)建的無(wú)名管道進(jìn)行通信,這樣它們倆就無(wú)法通過(guò)無(wú)名管道進(jìn)行通信痊银。