教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

C++培訓(xùn)之Linux 常見的六大IPC 通信方式(一)

更新時(shí)間:2016年08月26日16時(shí)24分 來源:傳智播客C++培訓(xùn)學(xué)院 瀏覽次數(shù):

Linux 常見的六大IPC 通信方式
 
Linux環(huán)境下,進(jìn)程地址空間相互獨(dú)立,每個(gè)進(jìn)程各自有不同的用戶地址空間。任何一個(gè)進(jìn)程的全局變量在另一個(gè)進(jìn)程中都看不到,所以進(jìn)程和進(jìn)程之間不能相互訪問,要交換數(shù)據(jù)必須通過內(nèi)核,在內(nèi)核中開辟一塊緩沖區(qū),進(jìn)程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進(jìn)程2再從內(nèi)核緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機(jī)制稱為進(jìn)程間通信(IPC,InterProcess Communication)。今天我們來看一下,Linux下常見的六大IPC通信方式。   

1、信號

    信號是Unix/Linux系統(tǒng)在一定條件下生成的事件。信號是一種異步通信機(jī)制,進(jìn)程不需要執(zhí)行任何操作來等待信號的到達(dá)。信號異步通知接收信號的進(jìn)程發(fā)生了某個(gè)事件,然后操作系統(tǒng)將會中斷接收到信號的進(jìn)程的執(zhí)行,轉(zhuǎn)而去執(zhí)行相應(yīng)的信號處理程序。
(1)注冊信號處理函數(shù)
        #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)發(fā)送信號
        #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秒后,向進(jìn)程本身發(fā)送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)

    管道用來連接不同進(jìn)程之間的數(shù)據(jù)流。
    (1)在兩個(gè)程序之間傳遞數(shù)據(jù)的最簡單的方法是使用popen()和pclose()函數(shù):
        #include <stdio.h>
        FILE *popen(const char *command, const char *open_mode);
        int pclose(FILE *stream);
    popen()函數(shù)首先調(diào)用一個(gè)shell,然后把command作為參數(shù)傳遞給shell。這樣每次調(diào)用popen()函數(shù)都需要啟動(dòng)兩個(gè)進(jìn)程;但是由于在Linux中,所有的參數(shù)擴(kuò)展(parameter expansion)都是由shell執(zhí)行的,這樣command中包含的所有參數(shù)擴(kuò)展都可以在command程序啟動(dòng)之前完成。
    (2)pipe()函數(shù):
     int pipe(int pipefd[2]);
    popen()函數(shù)只能返回一個(gè)管道描述符,并且返回的是文件流(file stream),可以使用函數(shù)fread()和fwrite()來訪問。pipe()函數(shù)可以返回兩個(gè)管道描述符:pipefd[0]pipefd[1],任何寫入pipefd[1]的數(shù)據(jù)都可以從pipefd[0]讀回;pipe()函數(shù)返回的是文件描述符(file descriptor),因此只能使用底層的read()和write()系統(tǒng)調(diào)用來訪問。pipe()函數(shù)通常用來實(shí)現(xiàn)父子進(jìn)程之間的通信。
    (3)命名管道:FIFO
       int mkfifo(const char *fifo_name, mode_t mode);
    前面兩種管道只能用在相關(guān)的程序之間,使用命名管道可以解決這個(gè)問題。在使用open()打開FIFO時(shí),mode中不能包含O_RDWR。mode最常用的是O_RDONLY,O_WRONLY與O_NONBLOCK的組合。O_NONBLOCK影響了read()和write()在FIFO上的執(zhí)行方式。
   

3、信號量(Semaphores)

    System V的信號量集表示的是一個(gè)或多個(gè)信號量的集合。內(nèi)核為每個(gè)信號量集維護(hù)一個(gè)semid_ds數(shù)據(jù)結(jié)構(gòu),而信號量集中的每個(gè)信號量使用一個(gè)無名結(jié)構(gòu)體表示,這個(gè)結(jié)構(gòu)體至少包含以下成員:
    struct{
        unsigned short semval;//信號量值,總是>=0
        pid_t sempid;  //上一次操作的pid
       …
    };
      (1)創(chuàng)建或訪問信號量
       int semget(key_t key,int nsems,int flag);
    nsems指定信號量集中信號量的個(gè)數(shù),如果只是獲取信號量集的標(biāo)識符(而非新建),那么nsems可以為0。flag的低9位作為信號量的訪問權(quán)限位,類似于文件的訪問權(quán)限;如果flag中同時(shí)指定了IPC_CREAT和IPC_EXCL,那么如果key已與現(xiàn)存IPC對象想關(guān)聯(lián)的話,函數(shù)將會返回EEXIST錯(cuò)誤。例如,flag可以為IPC_CREAT|0666。
    (2)控制信號量集
       int semctl(int semid,int semnum,int cmd,union semun arg);
    對semid信號量集合執(zhí)行cmd操作;cmd常用的兩個(gè)值是:SETVAL初始化第semnum個(gè)信號量的值為arg.val;IPC_RMID刪除信號量。
    (3)對一個(gè)或多個(gè)信號量進(jìn)行操作
     int semop(int semid,struct sembuf *sops,unsigned nsops);
     struct sembuf{
              unsigned short sem_num;  //信號量索引
              short   sem_op;     //對信號量進(jìn)行的操作,常用的兩個(gè)值為-1和+1,分別代表P、V操作
              short   sem_flag;   //比較重要的值是SEM_UNDO:當(dāng)進(jìn)程結(jié)束時(shí),相應(yīng)的操作將被取消;同時(shí),如果進(jìn)程結(jié)束時(shí)沒有釋放資源的話,系統(tǒng)會自動(dòng)釋放
           };

4、共享內(nèi)存

    共享內(nèi)存允許兩個(gè)或多個(gè)進(jìn)程共享一定的存儲區(qū),因?yàn)椴恍枰截悢?shù)據(jù),所以這是最快的一種IPC。
     (1)創(chuàng)建或訪問共享內(nèi)存
        int shmget(key_t key,size_t size,int shmflg);
    (2)附加共享內(nèi)存到進(jìn)程的地址空間
        void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常為NULL,由系統(tǒng)選擇共享內(nèi)存附加的地址;shmflg可以為SHM_RDONLY
    (3)從進(jìn)程的地址空間分離共享內(nèi)存
        * int shmdt(const void *shmaddr); //shmaddr是shmat()函數(shù)的返回值
    (4)控制共享內(nèi)存
       int shmctl(int shmid,int cmd,struct shmid_ds *buf);
       struct shmid_ds{
              struct ipc_perm shm_perm;
              …
          };
    cmd的常用取值有:(a)IPC_STAT獲取當(dāng)前共享內(nèi)存的shmid_ds結(jié)構(gòu)并保存在buf中(2)IPC_SET使用buf中的值設(shè)置當(dāng)前共享內(nèi)存的shmid_ds結(jié)構(gòu)(3)IPC_RMID刪除當(dāng)前共享內(nèi)存

 本文版權(quán)歸傳智播客C++培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處。謝謝!
作者:傳智播客C/C++培訓(xùn)學(xué)院
首發(fā):http://m.8y3kgpwe.cn/c/ 
0 分享到:
和我們在線交談!