?
8.7??實(shí)驗(yàn)內(nèi)容
8.7.1??管道通信實(shí)驗(yàn)
1.實(shí)驗(yàn)?zāi)康?/h4>
通過編寫有名管道多路通信實(shí)驗(yàn),讀者可進(jìn)一步掌握管道的創(chuàng)建、讀寫等操作,同時(shí),也復(fù)習(xí)使用select()函數(shù)實(shí)現(xiàn)管道的通信。
2.實(shí)驗(yàn)內(nèi)容
讀者還記得在6.3.3小節(jié)中,通過mknod命令創(chuàng)建兩個(gè)管道的實(shí)例嗎?本實(shí)例只是在它的基礎(chǔ)上添加有名管道的創(chuàng)建,而不用再輸入mknod命令。
3.實(shí)驗(yàn)步驟
(1)畫出流程圖。
該實(shí)驗(yàn)流程圖如圖8.9所示。
圖8.9??8.6.1實(shí)驗(yàn)流程圖
(2)編寫代碼。
該實(shí)驗(yàn)源代碼如下所示。
/*?pipe_select.c*/
#include?<fcntl.h>
#include?<stdio.h>
#include?<unistd.h>
#include?<stdlib.h>
#include?<string.h>
#include?<time.h>
#include?<errno.h>
#define?FIFO1???????????????"in1"
#define?FIFO2???????????????"in2"
#define?MAX_BUFFER_SIZE?????????1024??????????/*?緩沖區(qū)大小*/
#define?IN_FILES????????????3???????????????????/*?多路復(fù)用輸入文件數(shù)目*/
#define?TIME_DELAY??????????60??????????????/*?超時(shí)值秒數(shù)?*/
#define?MAX(a,?b)???????????((a?>?b)?(a):(b))
int?main(void)
{
?????int?fds[IN_FILES];
?????char?buf[MAX_BUFFER_SIZE];
?????int?i,?res,?real_read,?maxfd;
?????struct?timeval?tv;
?????fd_set?inset,tmp_inset;
????
?????fds[0]?=?0;????????
????
?????/*?創(chuàng)建兩個(gè)有名管道?*/
?????if?(access(FIFO1,?F_OK)?==?-1)?
?????{
????????if?((mkfifo(FIFO1,?0666)?<?0)?&&?(errno?!=?EEXIST))
????????{
????????????printf("Cannot?create?fifo?filen");
????????????exit(1);
????????}
?????}
?????if?(access(FIFO2,?F_OK)?==?-1)?
?????{
????????if?((mkfifo(FIFO2,?0666)?<?0)?&&?(errno?!=?EEXIST))
????????{
????????????printf("Cannot?create?fifo?filen");
????????????exit(1);
????????}
?????}
????????
?????/*?以只讀非阻塞方式打開兩個(gè)管道文件?*/
?????if((fds[1]?=?open?(FIFO1,?O_RDONLY|O_NONBLOCK))?<?0)
?????{
????????printf("Open?in1?errorn");
????????return?1;
?????}
????if((fds[2]?=?open?(FIFO2,?O_RDONLY|O_NONBLOCK))?<?0)
????{
????????printf("Open?in2?errorn");
????????return?1;
?????}
?????/*取出兩個(gè)文件描述符中的較大者*/
????maxfd?=?MAX(MAX(fds[0],?fds[1]),?fds[2]);
????/*初始化讀集合inset,并在讀文件描述符集合中加入相應(yīng)的描述集*/
????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)測(cè)試該文件描述符是否準(zhǔn)備就緒,并調(diào)用select()函數(shù)對(duì)相關(guān)文件描述符做相應(yīng)操作*/
????while(FD_ISSET(fds[0],&inset)?
?????????????||?FD_ISSET(fds[1],&inset)?||?FD_ISSET(fds[2],?&inset))
????{?
?????/*?文件描述符集合的備份,?免得每次進(jìn)行初始化?*/
????????tmp_inset?=?inset;?
????????res?=?select(maxfd?+?1,?&tmp_inset,?NULL,?NULL,?&tv);
????????switch(res)
????????{
????????????case?-1:
????????????{
??????????????????printf("Select?errorn");
??????????????????return?1;
??????????????}
??????????????break;??????????????????
??????????????case?0:?/*?Timeout?*/
??????????????{
??????????????????printf("Time?outn");
??????????????????return?1;
???????????}
????????????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)
??????????????????????????????{
??????????????????????????????????return?1;
??????????????????????????????}
?????????????????????? ?????}
???????????????????????????else?if?(!real_read)
???????????????????????????{
???????????????????????????????close(fds[i]);
???????????????????????????????FD_CLR(fds[i],?&inset);
??????????????????????????}
??????????????????????????else
??????????????????????????{
???????????????????????????????if?(i?==?0)
???????????????????????????????{/*?主程序終端控制?*/
??????????????????????????????????if?((buf[0]?==?'q')?||?(buf[0]?==?'Q'))
???? ??????????????????????????????{
?????????? ???????? ??????????????????return?1;
???????????????????????????????}
???????????????????????????????}
???????????????????????????????else
???????????????????????????????{/*?顯示管道輸入字符串?*/
???????????????????????????????????buf[real_read]?=?'