Linux IPC總結

來源:互聯網
上載者:User

IPC處理序間通訊(Inter-Process Communication)就是指多個進程之間相互連信,交換資訊的方法。Linux IPC基本上都是從Unix平台上繼承而來的。主要包括最初的Unix IPC,System V IPC以及基於Socket的IPC。另外,Linux也支援POSIX IPC。

System V,BSD,POSIX

    System V是Unix作業系統最早的商業發行版之一。它最初由AT&T(American Telephone & Telegraph)開發,最早在1983年發布。System V主要發行了4個版本,其中SVR4(System V Release 4)是最成功的版本。BSD(Berkeley Software Distribution,有時也被稱為Berkeley Unix)是加州大學於1977至1995年間開發的。在19世紀八十年代至九十年代之間,System V和BSD代表了Unix的兩種主要的操作風格。它們的主要區別如下:

    系統                      System V           BSD
    root指令碼位置            /etc/init.d/       /etc/rc.d/
    預設shell                 Bshell             Cshell
    檔案系統資料            /etc/mnttab     /etc/mtab
    核心位置                  /UNIX             /vmUnix
    印表機裝置                lp                  rlp
    字串函數                memcopy       bcopy
    終端初始化設定檔案    /etc/initab       /etc/ttys
    終端控制                  termio            termios

    Linux系統的操作風格往往介於這兩種風格之間。

    POSIX(Portable Operating System Interface [for Unix])是由IEEE(Institute of Electrical and Electronics Engineers,電子電氣工程協會)開發的。現有的大部分Unix都遵循POSIX標準,而Linux從一開始就遵循POSIX標準。

最初的Unix IPC

1、訊號

    訊號是Unix/Linux系統在一定條件下產生的事件。訊號是一種非同步通訊機制,進程不需要執行任何操作來等待訊號的到達。訊號非同步通知接收訊號的進程發生了某個事件,然後作業系統將會中斷接收到訊號的進程的執行,轉而去執行相應的訊號處理常式。

    (1)註冊訊號處理函數
        #include <signal.h>
        /*typedef void (*sighandler_t)(int);  sighandler_t signal(int signum,sighandler_t handler);*/
        * void (*signal(int signum, void (*handler)(int)))(int);  //SIG_IGN && SIG_DFL
        * int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

    (2)發送訊號
        #include <signal.h>
        * int kill(pid_t pid,int sig); //#include <sys/types.h> 
        * int raise(int sig);            //kill(getpid(),sig);
        * unsigned int alarm(unsigned int seconds); //(#include <unistd.h>) seconds秒後,向進程本身發送SIGALRM訊號。

    (3)訊號集
        訊號集被定義為:typedef struct {unsigned long sig[_NSIG_WORDS];} sigset_t;
        * int sigaddset(sigset_t *set,int sig);
        * int sigemptyset(sigset_t *set);

2、管道(Pipe)

    管道用來串連不同進程之間的資料流。

    (1)在兩個程式之間傳遞資料的最簡單的方法是使用popen()和pclose()函數:
        #include <stdio.h>
        FILE *popen(const char *command, const char *open_mode);
        int pclose(FILE *stream);
    popen()函數首先調用一個shell,然後把command作為參數傳遞給shell。這樣每次調用popen()函數都需要啟動兩個進程;但是由於在Linux中,所有的參數擴充(parameter expansion)都是由shell執行的,這樣command中包含的所有參數擴充都可以在command程式啟動之前完成。

    (2)pipe()函數:
        #include <unistd.h>
        int pipe(int pipefd[2]);
    popen()函數只能返回一個管道描述符,並且返回的是檔案流(file stream),可以使用函數fread()和fwrite()來訪問。pipe()函數可以返回兩個管道描述符:pipefd[0]pipefd[1],任何寫入pipefd[1]的資料都可以從pipefd[0]讀回;pipe()函數返回的是檔案描述符(file descriptor),因此只能使用底層的read()和write()系統調用來訪問。pipe()函數通常用來實現父子進程之間的通訊。

    (3)具名管道:FIFO
        #include <sys/types.h>
        #include <sys/stat.h>
        int mkfifo(const char *fifo_name, mode_t mode);
    前面兩種管道只能用在相關的程式之間,使用具名管道可以解決這個問題。在使用open()開啟FIFO時,mode中不能包含O_RDWR。mode最常用的是O_RDONLY,O_WRONLY與O_NONBLOCK的組合。O_NONBLOCK影響了read()和write()在FIFO上的執行方式。

    PS:要想查看庫函數用法,最可靠的資料來自Linux manual page:

    $sudo apt-get install manpages-dev

    $man 3 function_name

 

System V IPC

    System V IPC指的是AT&T在System V.2發行版中引入的三種處理序間通訊工具:(1)訊號量,用來管理對共用資源的訪問 (2)共用記憶體,用來高效地實現進程間的資料共用 (3)訊息佇列,用來實現進程間資料的傳遞。我們把這三種工具統稱為System V IPC的對象,每個對象都具有一個唯一的IPC標識符(identifier)。要保證不同的進程能夠擷取同一個IPC對象,必須提供一個IPC關鍵字(IPC key),核心負責把IPC關鍵字轉換成IPC標識符。   

    System V IPC具有相似的文法,一般操作如下:

    (1)選擇IPC關鍵字,可以使用如下三種方式:

       a)IPC_PRIVATE。由核心負責選擇一個關鍵字然後產生一個IPC對象並把IPC標識符直接傳遞給另一個進程。
       b)直接選擇一個關鍵字。
       c)使用ftok()函數產生一個關鍵字。

    (2)使用semget()/shmget()/msgget()函數根據IPC關鍵字key和一個標誌flag建立或訪問IPC對象。如果key是IPC_PRIVATE;或者key尚未與已經存在的IPC對象相關聯且flag中包含IPC_CREAT標誌,那麼就會建立一個全新的IPC對象。

    (3)使用semctl()/shmctl()/msgctl()函數修改IPC對象的屬性。

    (4)使用semctl()/shmctl()/msgctl()函數和IPC_RMID標誌銷毀IPC執行個體。

    System V IPC為每個IPC對象設定了一個ipc_perm結構體並在建立IPC對象的時候進行初始化。這個結構體中定義了IPC對象的存取權限和所有者:

    struct ipc_perm{
       uid_t uid;   //所有者的使用者id
       gid_t gid;   //所有者的組id
       uid_t cuid;  //建立者的使用者id
       gid_t cgid;  //建立者的組id
       mode_t mode; //訪問模式
       …
    };

    shell中管理IPC對象的命令是ipcs、ipcmk和ipcrm。

1、訊號量(Semaphores)

    System V的訊號量集表示的是一個或多個訊號量的集合。核心為每個訊號量集維護一個semid_ds資料結構,而訊號量集中的每個訊號量使用一個無名結構體表示,這個結構體至少包含以下成員:
    struct{
        unsigned short semval;//訊號量值,總是>=0
        pid_t sempid;  //上一次操作的pid
       …
    };

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    (1)建立或訪問訊號量
        * int semget(key_t key,int nsems,int flag); 
    nsems指定訊號量集中訊號量的個數,如果只是擷取訊號量集的標識符(而非建立),那麼nsems可以為0。flag的低9位作為訊號量的存取權限位,類似於檔案的存取權限;如果flag中同時指定了IPC_CREAT和IPC_EXCL,那麼如果key已與現存IPC對象想關聯的話,函數將會返回EEXIST錯誤。例如,flag可以為IPC_CREAT|0666。

    (2)控制訊號量集
        * int semctl(int semid,int semnum,int cmd,union semun arg);
    對semid訊號量集合執行cmd操作;cmd常用的兩個值是:SETVAL初始化第semnum個訊號量的值為arg.val;IPC_RMID刪除訊號量。

    (3)對一個或多個訊號量進行操作
        * int semop(int semid,struct sembuf *sops,unsigned nsops);
        * struct sembuf{
              unsigned short sem_num;  //訊號量索引
              short   sem_op;     //對訊號量進行的操作,常用的兩個值為-1和+1,分別代表P、V操作
              short   sem_flag;   //比較重要的值是SEM_UNDO:當進程結束時,相應的操作將被取消;同時,如果進程結束時沒有釋放資源的話,系統會自動釋放
           };

2、共用記憶體

    共用記憶體允許兩個或多個進程共用一定的儲存區,因為不需要拷貝資料,所以這是最快的一種IPC。

    #include <sys/ipc.h>
    #include <sys/shm.h>
    (1)建立或訪問共用記憶體
        * int shmget(key_t key,size_t size,int shmflg);

    (2)附加共用記憶體到進程的地址空間
        * void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常為NULL,由系統選擇共用記憶體附加的地址;shmflg可以為SHM_RDONLY

    (3)從進程的地址空間分離共用記憶體
        * int shmdt(const void *shmaddr); //shmaddr是shmat()函數的傳回值

    (4)控制共用記憶體
        * int shmctl(int shmid,int cmd,struct shmid_ds *buf);
        * struct shmid_ds{
              struct ipc_perm shm_perm;
              …
          }; 
    cmd的常用取值有:(a)IPC_STAT擷取當前共用記憶體的shmid_ds結構並儲存在buf中(2)IPC_SET使用buf中的值設定當前共用記憶體的shmid_ds結構(3)IPC_RMID刪除當前共用記憶體

3、訊息佇列

    訊息佇列儲存在核心中,是一個由訊息組成的鏈表。

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    (1)建立或訪問訊息佇列
    * int msgget(key_t key,int msgflg);

    (2)操作訊息佇列
        * int msgsnd(int msqid,const void *msg,size_t nbytes,int msgflg);
    msg指向的結構體必須以一個long int成員開頭,作為msgrcv()的訊息類型,必須大於0。nbytes指的是msg指向結構體的大小,但不包括long int部分的大小
        * ssize_t msgrcv(int msqid,void *msg,size_t nbytes,long msgtype,int msgflg);
    如果msgtype是0,就返回訊息佇列中的第一個訊息;如果是正整數,就返回隊列中的第一個該類型的訊息;如果是負數,就返回隊列中具有最小值的第一個訊息,並且該最小值要小於等於msgtype的絕對值。

    (3)控制訊息隊列
        * int msgctl(int msqid,int cmd,struct msqid_ds *buf);
        * struct msqid_ds{
              struct ipc_perm msg_perm;
              …
           };

Socket
  通訊端(Socket)是由Berkeley在BSD系統中引入的一種基於串連的IPC,是對網路介面(硬體)和網路通訊協定(軟體)的抽象。它既解決了無名管道只能在相關進程間單向通訊的問題,又解決了網路上不同主機之間無法通訊的問題。

  通訊端有三個屬性:域(domain)、類型(type)和協議(protocol),對應於不同的域,通訊端還有一個地址(address)來作為它的名字。

  域(domain)指定了通訊端通訊所用到的協議族,最常用的域是AF_INET,代表網路通訊端,底層協議是IP協議。對於網路通訊端,由於伺服器端有可能會提供多種服務,用戶端需要使用IP連接埠號碼來指定特定的服務。AF_UNIX代表本地通訊端,使用Unix/Linux檔案系統實現。

  IP協議提供了兩種通訊手段:流(streams)和資料報(datagrams),對應的通訊端類型(type)分別為流式通訊端和資料通訊端。流式通訊端(SOCK_STREAM)用於提供連線導向、可靠的Data Transmission Service。該服務保證資料能夠實現無差錯、無重複發送,並按順序接收。流式通訊端使用TCP協議。資料通訊端(SOCK_DGRAM)提供了一種不需連線的服務。該服務並不能保證資料轉送的可靠性,資料有可能在傳輸過程中丟失或出現資料重複,且無法保證順序地接收到資料。資料通訊端使用UDP協議。

  一種類型的通訊端可能可以使用多於一種的協議來實現,通訊端的協議(protocol)屬性用於指定一種特定的協議。

 

總結:

 

 

 

System V IPC API

 

1,訊息佇列

int ftok(const char *pathname, int prj_id);

int msgget(key_t key,int msgflag);

int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

int msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);

 

2,訊號量

int semget(key_t key,int nsems,int semflag);

int semctl(int semid,int semnum,int cmd,…);

int semop(int semid,struct sembuf *sops,unsigned nsops,struct timespec *timeout);

 

3,共用記憶體

int shmget(key_t key,size_t size,int shmflag);

int shmctl(int shmid,int cmd,struct shmid_ds *buf);

  

POSIX IPC API

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.