進程間通信之:實驗內(nèi)容
8.7實驗內(nèi)容
8.7.1管道通信實驗
1.實驗目的
通過編寫有名管道多路通信實驗,讀者可進一步掌握管道的創(chuàng)建、讀寫等操作,同時,也復習使用select()函數(shù)實現(xiàn)管道的通信。
2.實驗內(nèi)容
讀者還記得在6.3.3小節(jié)中,通過mknod命令創(chuàng)建兩個管道的實例嗎?本實例只是在它的基礎(chǔ)上添加有名管道的創(chuàng)建,而不用再輸入mknod命令。
3.實驗步驟
(1)畫出流程圖。
該實驗流程圖如圖8.9所示。
圖8.98.6.1實驗流程圖
(2)編寫代碼。
該實驗源代碼如下所示。
/*pipe_select.c*/
#includefcntl.h>
#includestdio.h>
#includeunistd.h>
#includestdlib.h>
#includestring.h>
#includetime.h>
#includeerrno.h>
#defineFIFO1in1
#defineFIFO2in2
#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;iIN_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ù)對相關(guān)文件描述符做相應操作*/
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;iIN_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_read0)
{
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]='