0 個人資訊
- 張櫻姿
- 201821121038
- 計算1812
1 實驗目的
- 掌握行程間通信管道的編程,
2 實驗內容
- 在服務器上用VIM撰寫一個程式:創建一個命名管道,創建兩個行程分別對管道進行讀(
read_fifo.c)和寫(write_fifo.c),給出源代碼 - 給出運行結果,并分析
3 實驗報告
3.1 撰寫寫管道程式(write_fifo.c)
1 #include<unistd.h> //write,read,close,access 2 #include<string.h> //memset 3 #include<errno.h> //errno 4 #include<fcntl.h> //open,O_WRONLY,O_RDONLY 5 #include<stdio.h> //printf,sscanf 6 #include<stdlib.h> //exit 7 #include<limits.h> //PIPE_BUF 8 9 #define MYFIFO "/tmp/myfifo" //有名管道檔案名 10 #define BUFES PIPE_BUF 11 12 int main(int argc,char * argv[]) 13 { 14 int fd,n; 15 char buff[BUFES]; 16 17 if(argc <= 1) 18 { 19 exit(1); 20 } 21 sscanf(argv[1],"%s",buff); 22 //以只寫阻塞方式打開FIFO管道 23 fd = open(MYFIFO,O_WRONLY); 24 if(fd==-1) 25 { 26 printf("Open fifo error\n"); 27 exit(1); 28 } 29 //向管道中寫入字串 30 if((n = write(fd,buff,BUFES))>0) 31 { 32 printf("Finish writing '%s' to FIFO\n",buff); 33 } 34 close(fd); 35 exit(0); 36 }
3.2 撰寫讀管道程式(read_fifo.c)
1 #include<unistd.h> //write,read,close,access 2 #include<string.h> //memset 3 #include<errno.h> //errno 4 #include<fcntl.h> //open,O_WRONLY,O_RDONLY 5 #include<stdio.h> //printf,sscanf 6 #include<stdlib.h> //exit 7 #include<limits.h> //PIPE_BUF 8 9 #define MYFIFO "/tmp/myfifo" 10 #define BUFES PIPE_BUF 11 12 int main() 13 { 14 int fd,n; 15 char buff[BUFES]; 16 //判斷有名管道是否已存在 17 if(access(MYFIFO,F_OK)==-1) 18 { //若不存在,則創建可讀可寫的有名管道 19 if((mkfifo(MYFIFO,0666)<0)&&(errno != EEXIST)) 20 { 21 printf("Could't create fifo\n"); 22 exit(1); 23 } 24 } 25 //以只讀阻塞方式打開有名管道 26 fd = open(MYFIFO,O_RDONLY); 27 if(fd==-1) 28 { 29 printf("Open fifo error\n"); 30 exit(1); 31 } 32 //不停讀取管道中的資料,如果沒用資料可讀,則一直處于阻塞狀態 33 while(1) 34 { 35 memset(buff,0,sizeof(buff)); 36 if((n = read(fd,buff,BUFES))>0) 37 { 38 printf("Read '%s' from FIFO\n",buff); 39 } 40 } 41 close(fd); 42 exit(0); 43 }
3.3 運行結果及分析
為了能夠較好地觀察運行結果,將兩程式分別編譯后,把這兩個程式分別在兩個終端里運行,在這里首先啟動讀管道程式,讀管道行程在建立管道后就開始回圈地從管道里讀出內容,如果沒有資料可讀,則一直阻塞到寫管道行程向管道寫入資料,在啟動了寫管道程式后,讀行程能夠從管道里讀出用戶的輸入內容,程式運行結果如下:


分析:
①對于讀行程:
· 若該管道是阻塞打開,且當前FIFO內無資料,則對讀行程而言一直阻塞到有資料寫入,
· 若該管道是非阻塞打開,則不論FIFO內是否有資料,都行程都會立即執行讀操作,也就是說若FIFO內無資料,那么讀程式將立馬回傳0,
此處使用的是阻塞方式,
②對于寫行程:
· 若該管道是阻塞打開,則寫行程將一直阻塞到有資料寫入,
· 若該管道是非阻塞打開而不能寫入全部資料,則對讀行程而言只能進行部分寫入或者呼叫失敗,
③管道模式:
· O_RDONLY:讀管道,
· O_WRONLY:寫管道,
· O_RDWR:讀寫管道,
· O_NONBLOCK:非阻塞,
· O_CREAT:如果該檔案不存在,就創建一個新的檔案,并使用第3個引數為其設定權限,
· O_EXCL:測驗檔案是否存在,如果使用O_CREAT|O_CREAT時檔案存在,那么將回傳出錯:errno == EEXIST,
3.4 創建兩個有名管道實作聊天程式
服務器端程式:
1 /*Server.c*/ 2 #include<unistd.h> 3 #include<string.h> 4 #include<errno.h> 5 #include<fcntl.h> 6 #include<stdio.h> 7 #include<stdlib.h> 8 #include<limits.h> 9 10 #define WRITE_FIFO "/tmp/readfifo" 11 #define READ_FIFO "/tmp/writefifo" 12 #define BUFES PIPE_BUF 13 14 int main(int argc,char * argv[]) 15 { 16 int wfd,rfd,n; 17 char buff[BUFES],readbuff[BUFES]; 18 //創建管道WRITE_FIFO 19 mkfifo(WRITE_FIFO, S_IFIFO|0666); 20 //以只讀阻塞方式打開FIFO管道 21 rfd = open(READ_FIFO,O_RDONLY); 22 //以只寫阻塞方式打開FIFO管道 23 wfd = open(WRITE_FIFO,O_WRONLY); 24 //不停讀取管道中的資料,如果沒用資料可讀,則一直處于阻塞狀態 25 while(1){ 26 memset(readbuff,0,sizeof(readbuff)); 27 if((n = read(rfd,readbuff,BUFES))>0) 28 { 29 readbuff[BUFES] = '\0'; 30 printf("Client: %s\n",readbuff); 31 } 32 memset(buff,0,sizeof(buff)); 33 printf("Server: "); 34 fgets(buff, BUFES, stdin); 35 buff[strlen(buff)-1] = '\0'; 36 37 write(wfd,buff,strlen(buff)); 38 } 39 close(wfd); 40 close(rfd); 41 exit(0); 42 }
客戶端程式:
1 /*Client.c*/ 2 #include<unistd.h> 3 #include<string.h> 4 #include<errno.h> 5 #include<fcntl.h> 6 #include<stdio.h> 7 #include<stdlib.h> 8 #include<limits.h> 9 10 #define WRITE_FIFO "/tmp/writefifo" 11 #define READ_FIFO "/tmp/readfifo" 12 #define BUFES PIPE_BUF 13 14 int main(int argc,char * argv[]) 15 { 16 int wfd,rfd,n; 17 char buff[BUFES],readbuff[BUFES]; 18 //創建管道READ_FIFO 19 mkfifo(WRITE_FIFO, S_IFIFO|0666); 20 //以只寫阻塞方式打開FIFO管道 21 wfd = open(WRITE_FIFO,O_WRONLY); 22 //以只讀阻塞方式打開FIFO管道 23 rfd = open(READ_FIFO,O_RDONLY); 24 //不停讀取管道中的資料,如果沒用資料可讀,則一直處于阻塞狀態 25 while(1) 26 { 27 memset(buff,0,sizeof(buff)); 28 printf("Client: "); 29 fgets(buff, BUFES, stdin); 30 buff[strlen(buff)-1] = '\0'; 31 32 write(wfd,buff,strlen(buff)); 33 memset(readbuff,0,sizeof(readbuff)); 34 if((n = read(rfd,readbuff,BUFES))>0) 35 { 36 printf("Server: %s\n",readbuff); 37 } 38 } 39 close(wfd); 40 close(rfd); 41 exit(0); 42 }
3.5 運行效果及分析


分析:在這里首先啟動客戶端程式,再啟動服務器端程式,客戶端在建立管道后,首先寫入資料到管道中,接著資料傳遞到服務器端,然后服務器端將資料寫入管道中,再傳遞到客戶端,如此往復回圈,如果沒有資料可讀,則一直阻塞到寫管道行程向管道寫入資料,
4 References
- https://blog.csdn.net/ccskyer/article/details/24989961
- https://blog.csdn.net/MONKEY_D_MENG/article/details/5570468
- https://blog.csdn.net/CSDN_LQR/article/details/52170717
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/103621.html
標籤:Linux
