進程間通信之:實驗內(nèi)容
通過編寫有名管道多路通信實驗,讀者可進一步掌握管道的創(chuàng)建、讀寫等操作,同時,也復習使用select()函數(shù)實現(xiàn)管道的通信。
2.實驗內(nèi)容讀者還記得在6.3.3小節(jié)中,通過mknod命令創(chuàng)建兩個管道的實例嗎?本實例只是在它的基礎上添加有名管道的創(chuàng)建,而不用再輸入mknod命令。
3.實驗步驟(1)畫出流程圖。
該實驗流程圖如圖8.9所示。
圖8.98.6.1實驗流程圖
(2)編寫代碼。
該實驗源代碼如下所示。
/*pipe_select.c*/
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<errno.h>
#defineFIFO1"in1"
#defineFIFO2"in2"
#defineMAX_BUFFER_SIZE1024/*緩沖區(qū)大小*/
#defineIN_FILES3/*多路復用輸入文件數(shù)目*/
#defineTIME_DELAY60/*超時值秒數(shù)*/
#defineMAX(a,b)((a>b)?(a):(b))
intmain(void)
{
intfds[IN_FILES];
charbuf[MAX_BUFFER_SIZE];
inti,res,real_read,maxfd;
structtimevaltv;
fd_setinset,tmp_inset;
fds[0]=0;
/*創(chuàng)建兩個有名管道*/
if(access(FIFO1,F_OK)==-1)
{
if((mkfifo(FIFO1,0666)<0)&&(errno!=EEXIST))
{
printf("Cannotcreatefifofilen");
exit(1);
}
}
if(access(FIFO2,F_OK)==-1)
{
if((mkfifo(FIFO2,0666)<0)&&(errno!=EEXIST))
{
printf("Cannotcreatefifofilen");
exit(1);
}
}
/*以只讀非阻塞方式打開兩個管道文件*/
if((fds[1]=open(FIFO1,O_RDONLY|O_NONBLOCK))<0)
{
printf("Openin1errorn");
return1;
}
if((fds[2]=open(FIFO2,O_RDONLY|O_NONBLOCK))<0)
{
printf("Openin2errorn");
return1;
}
/*取出兩個文件描述符中的較大者*/
maxfd=MAX(MAX(fds[0],fds[1]),fds[2]);
/*初始化讀集合inset,并在讀文件描述符集合中加入相應的描述集*/
FD_ZERO(&inset);
for(i=0;i<IN_FILES;i++)
{
FD_SET(fds[i],&inset);
}
FD_SET(0,&inset);
tv.tv_sec=TIME_DELAY;
tv.tv_usec=0;
/*循環(huán)測試該文件描述符是否準備就緒,并調(diào)用select()函數(shù)對相關文件描述符做相應操作*/
while(FD_ISSET(fds[0],&inset)
||FD_ISSET(fds[1],&inset)||FD_ISSET(fds[2],&inset))
{
/*文件描述符集合的備份,免得每次進行初始化*/
tmp_inset=inset;
res=select(maxfd+1,&tmp_inset,NULL,NULL,&tv);
switch(res)
{
case-1:
{
printf("Selecterrorn");
return1;
}
break;
case0:/*Timeout*/
{
printf("Timeoutn");
return1;
}
break;
default:
{
for(i=0;i<IN_FILES;i++)
{
if(FD_ISSET(fds[i],&tmp_inset))
{
memset(buf,0,MAX_BUFFER_SIZE);
real_read=read(fds[i],buf,MAX_BUFFER_SIZE);
if(real_read<0)
{
if(errno!=EAGAIN)
{
return1;
}
}
elseif(!real_read)
{
close(fds[i]);
FD_CLR(fds[i],&inset);
}
else
{
if(i==0)
{/*主程序終端控制*/
if((buf[0]=='q')||(buf[0]=='Q'))
{
return1;
}
}
else
{/*顯示管道輸入字符串*/
buf[real_read]='