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

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

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

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

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

1、信號

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

    管道用來連接不同進程之間的數(shù)據(jù)流。
    (1)在兩個程序之間傳遞數(shù)據(jù)的最簡單的方法是使用popen()和pclose()函數(shù):
        #include <stdio.h>
        FILE *popen(const char *command, const char *open_mode);
        int pclose(FILE *stream);
    popen()函數(shù)首先調用一個shell,然后把command作為參數(shù)傳遞給shell。這樣每次調用popen()函數(shù)都需要啟動兩個進程;但是由于在Linux中,所有的參數(shù)擴展(parameter expansion)都是由shell執(zhí)行的,這樣command中包含的所有參數(shù)擴展都可以在command程序啟動之前完成。
    (2)pipe()函數(shù):
     int pipe(int pipefd[2]);
    popen()函數(shù)只能返回一個管道描述符,并且返回的是文件流(file stream),可以使用函數(shù)fread()和fwrite()來訪問。pipe()函數(shù)可以返回兩個管道描述符:pipefd[0]pipefd[1],任何寫入pipefd[1]的數(shù)據(jù)都可以從pipefd[0]讀回;pipe()函數(shù)返回的是文件描述符(file descriptor),因此只能使用底層的read()和write()系統(tǒng)調用來訪問。pipe()函數(shù)通常用來實現(xiàn)父子進程之間的通信。
    (3)命名管道:FIFO
       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上的執(zhí)行方式。
   

3、信號量(Semaphores)

    System V的信號量集表示的是一個或多個信號量的集合。內(nèi)核為每個信號量集維護一個semid_ds數(shù)據(jù)結構,而信號量集中的每個信號量使用一個無名結構體表示,這個結構體至少包含以下成員:
    struct{
        unsigned short semval;//信號量值,總是>=0
        pid_t sempid;  //上一次操作的pid
       …
    };
      (1)創(chuàng)建或訪問信號量
       int semget(key_t key,int nsems,int flag);
    nsems指定信號量集中信號量的個數(shù),如果只是獲取信號量集的標識符(而非新建),那么nsems可以為0。flag的低9位作為信號量的訪問權限位,類似于文件的訪問權限;如果flag中同時指定了IPC_CREAT和IPC_EXCL,那么如果key已與現(xiàn)存IPC對象想關聯(lián)的話,函數(shù)將會返回EEXIST錯誤。例如,flag可以為IPC_CREAT|0666。
    (2)控制信號量集
       int semctl(int semid,int semnum,int cmd,union semun arg);
    對semid信號量集合執(zhí)行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:當進程結束時,相應的操作將被取消;同時,如果進程結束時沒有釋放資源的話,系統(tǒng)會自動釋放
           };

4、共享內(nèi)存

    共享內(nèi)存允許兩個或多個進程共享一定的存儲區(qū),因為不需要拷貝數(shù)據(jù),所以這是最快的一種IPC。
     (1)創(chuàng)建或訪問共享內(nèi)存
        int shmget(key_t key,size_t size,int shmflg);
    (2)附加共享內(nèi)存到進程的地址空間
        void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常為NULL,由系統(tǒng)選擇共享內(nèi)存附加的地址;shmflg可以為SHM_RDONLY
    (3)從進程的地址空間分離共享內(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獲取當前共享內(nèi)存的shmid_ds結構并保存在buf中(2)IPC_SET使用buf中的值設置當前共享內(nèi)存的shmid_ds結構(3)IPC_RMID刪除當前共享內(nèi)存

 本文版權歸傳智播客C++培訓學院所有,歡迎轉載,轉載請注明作者出處。謝謝!
作者:傳智播客C/C++培訓學院
首發(fā):http://oisangadgets.com/c/ 
0 分享到:
和我們在線交談!