有名管道的使用
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> int main(int argc, char* argv[])//EXE send_fifo recv_fifo {/* A創(chuàng)建管道1,我們假定其先發(fā)消息,再收消息 *//* 管道2由B創(chuàng)建 */printf("create a fifo_1...\n");if(-1 == mkfifo(argv[1], 0666)){perror("mkfifo");exit(1);}printf("finish make fifo_1 !\n");/* A以寫方式打開管道1,以讀方式打開管道2 */int fd_send, fd_recv ;printf("open fifo....\n");fd_send = open(argv[1], O_WRONLY);fd_recv = open(argv[2], O_RDONLY);if(fd_send == -1 || fd_recv == -1){perror("open");unlink(argv[1]); /* 如果打開管道失敗,刪除A自己創(chuàng)建的管道1 */exit(1);}printf("open fifo sucess ! \n");/* 發(fā)送以及接受消息 *//* A先發(fā)消息*/char send_buf[1024];char recv_buf[1024];int send_flag = 0 ; /* 默認(rèn)沒有發(fā)完 */int recv_flag = 0 ; /* 默認(rèn)沒有接完 *//* 只要*/while(recv_flag == 0 || send_flag == 0){memset(send_buf, 0 ,1024);if(send_flag == 0 && fgets(send_buf, 1024, stdin) == NULL) // ctrl+d會(huì)使fgets返回NULL,代表發(fā)送結(jié)束{close(fd_send);send_flag = 1 ;}else if (send_flag == 0){write(fd_send, send_buf, strlen(send_buf));}/* 假定A沒有發(fā)完,當(dāng)程序執(zhí)行完第一個(gè)if語句時(shí),開始執(zhí)行第二個(gè)if語句時(shí),read發(fā)生阻塞,等待從管道中讀消息。此時(shí)必須等到B執(zhí)行第二個(gè)if語句,發(fā)送消息,即B往管道里寫東西,A才可以接受消息 *//* tip1:只要對(duì)方的寫端沒有關(guān)閉,那么read不會(huì)返回0,而是等待從管道中讀取信息 *//* tip2:A執(zhí)行第一個(gè)if語句往管道中寫入東西后,B幾乎是在同時(shí)接受到消息的(B的第一個(gè)if語句)*/memset(recv_buf, 0, 1024);if(recv_flag == 0 && read(fd_recv, recv_buf, 1024) == 0){recv_flag = 1 ;close(fd_recv);}else if(recv_flag == 0){write(1, recv_buf, strlen(recv_buf));}}printf("A over ! \n");unlink(argv[1]);//unlink(argv[2]);return 0 ; }
//第二個(gè)程序先收后發(fā) #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> int main(int argc, char* argv[])//EXE send_fifo recv_fifo {/* B創(chuàng)建管道2,我們假定其先收消息,再發(fā)消息 *//* 管道1由A創(chuàng)建 */printf("create a fifo_2...\n")if(-1 == mkfifo(argv[2], 0666)){perror("mkfifo");exit(1);}printf("finish make fifo_2 !\n");/* B以讀方式打開管道1,以寫方式打開管道2 */int fd_send, fd_recv ;printf("open fifo....\n");fd_recv = open(argv[1], O_RDONLY);fd_send = open(argv[2], O_WRONLY);if(fd_send == -1 || fd_recv == -1){perror("open");unlink(argv[2]); /* 如果打開管道失敗,刪除B自己創(chuàng)建的管道2 */exit(1);}printf("open fifo sucess ! \n");/* 接收以及發(fā)送消息 *//* B先接收消息*/char send_buf[1024];char recv_buf[1024];int send_flag = 0 ; /* 默認(rèn)沒有發(fā)完 */int recv_flag = 0 ; /* 默認(rèn)沒有接完 */while(recv_flag == 0 || send_flag == 0){memset(recv_buf, 0, 1024);if(recv_flag == 0 && read(fd_recv, recv_buf, 1024) == 0){recv_flag = 1 ;close(fd_recv);}else if(recv_flag == 0){write(1, recv_buf, strlen(recv_buf));}/* 上面第一個(gè)if語句執(zhí)行完后,B讀完之前A發(fā)送的消息,A與B的第一個(gè)if語句幾乎同時(shí)完成*/memset(send_buf, 0 ,1024);if(send_flag == 0 && fgets(send_buf, 1024, stdin) == NULL) // ctrl+d會(huì)使fgets返回NULL,代表發(fā)送結(jié)束{close(fd_send);send_flag = 1 ;}else if (send_flag == 0){write(fd_send, send_buf, strlen(send_buf));}}printf("B over ! \n");unlink(argv[2]);//unlink(argv[2]);return 0 ; }
思路
用戶A?????????????????????? 用戶B
寫??????? (管道)????????? 讀
讀??????? (管道)????????? 寫
此篇博文實(shí)現(xiàn)的雙方一發(fā)一收即為上圖所描述的。建立兩條管道,一條負(fù)責(zé)由A傳消息給B,另一條負(fù)責(zé)由B發(fā)消息給A。
當(dāng)用戶A發(fā)消息給B時(shí),B可以立即讀到消息。此時(shí)A的read為阻塞,必須等到用戶B發(fā)消息給A,A讀到消息后,A才可以繼續(xù)發(fā)消息給B。即之前博文的程序,無法實(shí)現(xiàn)A連續(xù)發(fā)送消息給B。
因此在改進(jìn)該程序中,我們會(huì)在每個(gè)用戶中,fork出一個(gè)子進(jìn)程。使用一個(gè)進(jìn)程負(fù)責(zé)發(fā)消息,一個(gè)進(jìn)程負(fù)責(zé)收消息。這樣就可以實(shí)現(xiàn)一方連續(xù)發(fā)送消息了。
注意,如果A使用子進(jìn)程進(jìn)行發(fā)送消息(w),那么就把子進(jìn)程的讀端(r)關(guān)閉;同理,父進(jìn)程負(fù)責(zé)接收消息(r),就把其寫端關(guān)閉(w)。原因?舉例來說,如果不把父進(jìn)程的寫端(w)關(guān)上,那么即使關(guān)閉了子進(jìn)程的寫端(w),用戶B的read還會(huì)阻塞,返回不了0,讀端(r)就無法關(guān)閉。
小結(jié)
對(duì)于管道間通信而言,每個(gè)進(jìn)程要專心做自己的事情,一定要把自己用不到的端口關(guān)閉。
注意
針對(duì)管道,read的返回值有如下3種情況:
1. 讀取正常,返回讀到的字符個(gè)數(shù)
2. 對(duì)方寫端關(guān)閉,read返回0
3. 自己的讀端關(guān)閉,read出錯(cuò),返回-1。
當(dāng)往一個(gè)讀端已關(guān)閉的管道里發(fā)消息時(shí),系統(tǒng)會(huì)掛掉該發(fā)消息的進(jìn)程。
其中的一個(gè)程序的例子
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> int main(int argc, char* argv[])//EXE send_fifo recv_fifo {/* A創(chuàng)建管道1,我們假定其先發(fā)消息,再收消息 *//* 管道2由B創(chuàng)建 */printf("create a fifo_1...\n");if(-1 == mkfifo(argv[1], 0666)){perror("mkfifo");exit(1);}printf("finish make fifo_1 !\n");/* A以寫方式打開管道1,以讀方式打開管道2 */int fd_send, fd_recv ;printf("open fifo....\n");fd_send = open(argv[1], O_WRONLY);fd_recv = open(argv[2], O_RDONLY);if(fd_send == -1 || fd_recv == -1){perror("open");unlink(argv[1]); /* 如果打開管道失敗,刪除A自己創(chuàng)建的管道1 */exit(1);}printf("open fifo sucess ! \n");char send_buf[1024];char recv_buf[1024];/* child負(fù)責(zé)接收消息 */if(fork() == 0){close(fd_send);while(memset(recv_buf,0,1024), read(fd_recv, recv_buf , 1024) > 0){write(1,recv_buf,strlen(recv_buf));}close(fd_recv);exit(1);}/* parent負(fù)責(zé)發(fā)送消息 */close(fd_recv);while(memset(send_buf,0,1024), fgets(send_buf,1024,stdin) != NULL){write(fd_send, send_buf,strlen(send_buf));}close(fd_send);wait(NULL);printf("A over ! \n");unlink(argv[1]);//unlink(argv[2]);return 0 ; } 另一個(gè)程序做相應(yīng)的修改另一個(gè)改成是先收后發(fā)!以讀方式打開管道1,以寫方式打開管道2
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> int main(int argc, char* argv[])//EXE send_fifo recv_fifo {printf("create a fifo_1...\n");if(-1 == mkfifo(argv[2], 0666)){perror("mkfifo");exit(1);}printf("finish make fifo_1 !\n");int fd_send, fd_recv ;printf("open fifo....\n"); //這里的順序不能變,否則死鎖 ;這里是打開;下面收發(fā)的順序可以改變,但還沒測試
fd_recv = open(argv[1], O_RDONLY);fd_send = open(argv[2], O_WRONLY);
if(fd_send == -1 || fd_recv == -1){perror("open");unlink(argv[2]); /* 如果打開管道失敗,刪除A自己創(chuàng)建的管道1 */exit(1);}printf("open fifo sucess ! \n");char send_buf[1024];char recv_buf[1024];/* child負(fù)責(zé)接收消息 */if(fork() == 0){close(fd_send);while(memset(recv_buf,0,1024), read(fd_recv, recv_buf , 1024) > 0){write(1,recv_buf,strlen(recv_buf));}close(fd_recv);exit(1);}/* parent負(fù)責(zé)發(fā)送消息 */close(fd_recv);while(memset(send_buf,0,1024), fgets(send_buf,1024,stdin) != NULL){write(fd_send, send_buf,strlen(send_buf));}close(fd_send);wait(NULL);printf("A over ! \n");unlink(argv[1]);//unlink(argv[2]);return 0 ; }
轉(zhuǎn)載于:https://www.cnblogs.com/hxjbc/p/3958619.html
總結(jié)
- 上一篇: Large-Scale Named En
- 下一篇: NGUI-Tweens