Linux系統程式設計之程式間通訊方式:管道(二)
管道的特點
每個管道只有一個頁面作為緩衝區,該頁面是按照環形緩衝區的方式來使用的。這種訪問方式是典型的“ 生產者 —— 消費者 ” 模型。當 “ 生產者 ” 程式有大量的資料需要寫時,而且每當寫滿一個頁面就需要進行睡眠等待,等待 “ 消費者 ” 從管道中讀走一些資料,為其騰出一些空間。相應的,如果管道中沒有可讀資料, “ 消費者 ” 程式就要睡眠等待,具體過程如下圖所示:
預設的情況下,從管道中讀寫資料,最主要的特點就是阻塞問題(這一特點應該記住),當管道里沒有資料,另一個程式預設用read() 函式從管道中讀資料是阻塞的。
測試程式碼如下:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc,char*argv[])
{
int fd_pipe[2]={0};
pid_t pid;
if(pipe(fd_pipe)<0){// 建立無名管道
perror("pipe");
}
pid=fork();// 建立程式
if(pid<0){// 出錯
perror("fork");
exit(-1);
}
if(pid==0){// 子程式
_exit(0);
}else if(pid>0){// 父程式
wait(NULL);// 等待子程式結束,回收其資源
char str[50]={0};
printf("before read\n");
// 從管道里讀資料,如果管道沒有資料, read() 會阻塞
read(fd_pipe[0],str,sizeof(str));
printf("after read\n");
printf("str=[%s]\n",str);// 列印資料
}
return 0;
}
執行結果:
當然,我們程式設計時可透過fcntl() 函式設定檔案的阻塞特性。
設定為阻塞:fcntl(fd,F_SETFL,0);
設定為非阻塞:fcntl(fd,F_SETFL,O_NONBLOCK);
測試程式碼如下:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
int main(int argc,char*argv[])
{
int fd_pipe[2]={0};
pid_t pid;
if(pipe(fd_pipe)<0){// 建立無名管道
perror("pipe");
}
pid=fork();// 建立程式
if(pid<0){// 出錯
perror("fork");
exit(-1);
}
if(pid==0){// 子程式
sleep(3);
char buf[]="hello,edu";
write(fd_pipe[1],buf,strlen(buf));// 寫資料
_exit(0);
}else if(pid>0){// 父程式
fcntl(fd_pipe[0],F_SETFL,O_NONBLOCK);// 非阻塞
//fcntl(fd_pipe[0],F_SETFL,0);// 阻塞
while(1){
char str[50]={0};
read(fd_pipe[0],str,sizeof(str));// 讀資料
printf("str=[%s]\n",str);
sleep(1);
}
}
return 0;
}
執行結果:
預設的情況下,從管道中讀寫資料,還有如下特點(知道有這麼回事就夠了,不用刻意去記這些特點):
1 )呼叫 write() 函式向管道里寫資料,當緩衝區已滿時 write() 也會阻塞。
測試程式碼如下:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc,char*argv[])
{
int fd_pipe[2]={0};
pid_t pid;
char buf[1024]={0};
memset(buf,'a',sizeof(buf));// 往管道寫的內容
int i=0;
if(pipe(fd_pipe)<0){// 建立無名管道
perror("pipe");
}
pid=fork();// 建立程式
if(pid<0){// 出錯
perror("fork");
exit(-1);
}
if(pid==0){// 子程式
while(1){
write(fd_pipe[1],buf,sizeof(buf));
i++;
printf("i========%d\n",i);
}
_exit(0);
}else if(pid>0){// 父程式
wait(NULL);// 等待子程式結束,回收其資源
}
return 0;
}
執行結果:
2 )通訊過程中,別的程式先結束後,當前程式讀埠關閉後,向管道內寫資料時, write() 所在程式會(收到 SIGPIPE 訊號)退出,收到 SIGPIPE 預設動作為中斷當前程式。
測試程式碼如下:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc,char*argv[])
{
int fd_pipe[2]={0};
pid_t pid;
if(pipe(fd_pipe)<0){// 建立無名管道
perror("pipe");
}
pid=fork();// 建立程式
if(pid<0){// 出錯
perror("fork");
exit(-1);
}
if(pid==0){// 子程式
//close(fd_pipe[0]);
_exit(0);
}else if(pid>0){// 父程式
wait(NULL);// 等待子程式結束,回收其資源
close(fd_pipe[0]);// 當前程式讀埠關閉
char buf[50]="12345";
// 當前程式讀埠關閉
//write() 會收到 SIGPIPE 訊號,預設動作為中斷當前程式
write(fd_pipe[1],buf,strlen(buf));
while(1);// 阻塞
}
return 0;
}
執行結果:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69914734/viewspace-2657157/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux系統程式設計之程式間通訊方式:命名管道(二)Linux程式設計
- Linux系統程式設計之程式間通訊方式:管道(一)Linux程式設計
- Linux系統程式設計之程式間通訊方式:命名管道(一)Linux程式設計
- Linux系統程式設計之程式間通訊方式:訊息佇列Linux程式設計佇列
- linux 程式間通訊之管道Linux
- 系統程式設計——管道通訊程式設計
- Linux系統程式設計之程式間通訊方式:共享記憶體例項演示Linux程式設計記憶體
- Linux系統程式設計之匿名管道Linux程式設計
- Linux 的程式間通訊:管道Linux
- Linux程式間通訊②:有名管道FIFOLinux
- linux程式間通訊--管道(PIPE & FIFO)Linux
- 【linux】系統程式設計-1-程式、管道和訊號Linux程式設計
- Linux系統程式設計—有名管道Linux程式設計
- Linux作業系統 程式之間的通訊Linux作業系統
- 溫故之.NET程式間通訊——管道
- Linux系統程式設計之命名管道與共享記憶體Linux程式設計記憶體
- 什麼是程式間通訊?Linux程式間通訊有幾種方式?Linux
- 程式間通訊是什麼?Linux程式間通訊有幾種方式?Linux
- linux 程式間通訊之FIFOLinux
- Linux程式之間如何通訊?Linux
- Linux 下的程式間通訊:使用管道和訊息佇列Linux佇列
- Linux環境程式設計程式間通訊機制理解Linux程式設計
- Linux系統程式設計之程式介紹Linux程式設計
- linux環境程式設計(2): 使用pipe完成程式間通訊Linux程式設計
- 程式間通訊——LINUXLinux
- Linux程式間通訊Linux
- Linux系統程式設計——特殊程式之孤兒程式Linux程式設計
- 【Linux系統程式設計】Linux訊號列表Linux程式設計
- Linux系統程式設計:訊號捕捉Linux程式設計
- Linux系統程式設計—訊號捕捉Linux程式設計
- linux環境程式設計(3): 使用POSIX IPC完成程式間通訊Linux程式設計
- 20.2、python程式間通訊——佇列和管道Python佇列
- Linux程式間的通訊方式有哪些?Linux入門教程Linux
- Linux 程式間通訊之System V 訊號量Linux
- 程式間通訊方式有哪些?
- Linux程式設計之gdb(二)Linux程式設計
- Linux程式間通訊-eventfdLinux
- Linux程式間通訊之共享記憶體Linux記憶體