進程間通訊(一)—管道

我會用幾篇博客總結一下在Linux中進程之間通訊的幾種方法,我會把這個開頭的摘要部分在這個系列的每篇博客中都打出來html

進程之間通訊的方式app

  • 管道
  • 消息隊列
  • 信號
  • 信號量
  • 共享存儲區
  • 套接字(socket)

進程間通訊(二)—消息隊列傳送門:http://www.cnblogs.com/lenomirei/p/5642575.htmlsocket

進程間通訊(三)—信號量傳送門:http://www.cnblogs.com/lenomirei/p/5649792.html函數

進程間通訊(四)—共享存儲區傳送門:http://www.cnblogs.com/lenomirei/p/5651995.htmlspa

進程間通訊(五)—信號傳送門:http://www.cnblogs.com/lenomirei/p/5656449.htmlcode

在以一切皆文件爲原則的Linux系統中,管道也是一種文件(特殊文件),能夠使用mkfifo命令建立一個管道文件server

 

在管道文件的前面有一個p來標識管道文件htm

 

此次主要說的是經過管道完成進程之間的通訊,經過管道通訊有兩種方式。blog

一種是匿名管道,一種是命名管道繼承

 

  • 匿名管道


先來看一段代碼

 

 1 #define MAXLINE 80
 2 int main()  3 {  4     int n;  5     int fd[2];  6  pid_t pid;  7     char line[MAXLINE];  8     if (pipe(fd) < 0)  9         perror("pipe"); 10     if ((pid = fork()) < 0) 11         perror("fork"); 12     if (pid > 0) 13  { 14         //father
15         close(fd[0]); 16  } 17     else
18  { 19         close(fd[1]); 20         n = read(fd[0], line, MAXLINE); 21         write(stdout, line, n);//寫到標準輸出上看一下效果
22  } 23     return 0; 24 
25 }

這個程序就是一個簡單的父子進程之間經過管道進行通訊的一個例子,具體的工做過程我用畫圖的方式展示出來

 

注意這一個步驟是十分重要的,若是不關閉相應的端口,就沒法正確操做管道。

匿名管道主要利用了,建立子進程的時候會把父進程的文件描述符表拷貝一份這個特徵,經過這個特徵,父子進程就看到了一個公共的資源—管道,並同時擁有對該管道腹瀉的權利,那麼一方讀,一方寫,就能夠完成進程之間的通訊了。

所謂的匿名管道就是說,沒有名字。。。你根本不知道這個管道文件存放在哪,也不知道這個管道文件的文件名,惟一跟這個跟管道文件有聯繫的只有父子進程中的文件描述符。那麼根據匿名管道的實現機制,很容易就能看出他的優缺點。

 

  • 管道的n個特徵
    • 管道是依賴於文件系統的,建立好管道以後,必定要關閉不使用的讀寫端
    • 只有父子進程才能夠使用管道通訊,也就是所謂的有血緣關係的進程進行進程間通訊。(匿名管道獨有)
    • 管道是基於數據流的,面向字節流!(後面會提到消息隊列是面向數據塊的,對比來看會好懂一些)
    • 管道只能稱之爲單向數據通訊,連半雙工都算不上
    • 同步與互斥問題不須要考慮了,管道已經考慮了
    • 當父子進程退出的時候,管道的生命週期就結束了,也就是說管道的生命週期就是進程

上述就是匿名管道的使用和實現機制,能夠看出必須有「親緣關係」的進程之間才能夠使用匿名管道來完成進程間通訊。父子進程固然能夠,「孫子」進程也是能夠的~

 

那麼爲了解決只有有親緣關係的進程才能使用這種方式進行通訊的弊端,就有了命名管道的通訊方式

  • 命名管道

簡單的來講,咱們剛纔使用的匿名管道是由於不知道文件名和存放路徑,因此只能經過繼承文件描述符表來得到跟匿名管道創建聯繫的方式,若是咱們知道路徑和管道文件名呢?那不就能夠完成非親緣關係的進程間通訊了麼

  • 函數原型  int mkfifo(const char *pathname,mode_t mode)
  • 其中第一個參數pathname就是路徑了,mode 就是建立的管道的訪問權限umask
  • 頭文件:#include <sys.stat.h>  #include <sys/types.h>
  • 返回值,成功返回0,失敗返回-1

下面貼上代碼

 這個是server的

    1 #include <sys/types.h>                                             
    2 #include <sys/stat.h>                                              
    3 #include <stdio.h>                                                 
    4 #include <unistd.h>                                                
    5 #include <stdlib.h>                                                
    6 #include <errno.h>                                                 
    7 #include <string.h>                                                
    8 #include <fcntl.h>                                                 
    9 #define _PATH_NAME_ "./pp"                                         
   10                                                                    
   11 int main() 12 { >> 13   char *str="hello world"; 14   int fd; 15   if(mkfifo(_PATH_NAME_,0644)<016 { 17     printf("hahaha\n"); 18     printf("mkfifo error %d:%s\n",errno,strerror(errno)); 19 } 20   fd=open(_PATH_NAME_,O_WRONLY); 21 write(fd,str,strlen(str)); 22   return 0; 23 }                                                                  

這個是client的

  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <stdlib.h>
  7 #include <errno.h>
  8 #include <string.h>
  9 #include <fcntl.h>
 10    
 11 #define _PATH_NAME_ "./pp"
 12    
 13    
 14 int main() 15 { 16   int fd; 17   fd=open(_PATH_NAME_,O_RDONLY); 18   char buf[1024]={'\0'}; 19   read(fd,buf,1024); 20   printf("%s\n",buf); 21   return 0; 22 }  

能夠經過open函數來打開分別使用read和write函數來讀寫管道,固然也能夠close掉標準輸入輸出,作成重定向的那樣也是能夠的

 

那麼管道有多大呢,咱們能夠往裏面扔多少數據呢?

既然管道也是一個文件,那麼確定有大小上限,這也是其一個缺點,大小有限的,那麼咱們究竟能夠寫多少數據放進管道呢,使用man 7 pipe命令打開pipe的說明文檔,能夠看見這麼一段

Pipe capacity
A pipe has a limited capacity. If the pipe is full, then a write(2)
will block or fail, depending on whether the O_NONBLOCK flag is set
(see below). Different implementations have different limits for the
pipe capacity. Applications should not rely on a particular capacity:
an application should be designed so that a reading process consumes
data as soon as it is available, so that a writing process does not
remain blocked.

In Linux versions before 2.6.11, the capacity of a pipe was the same as
the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11,
the pipe capacity is 65536 bytes.

看,我如今的版本是2.6.11以後了,因此是65536字節,之間的版本就是4096字節

 

最後的最後,來一個管道最大的缺點,管道是基於文件系統的!因此無論是讀仍是寫,都要求訪問磁盤進行I/O操做,I/O的速度你懂得,特別慢,因此不適合作多個client的結構,否則會很慢

相關文章
相關標籤/搜索