【Linux計劃】XSI IPC

來源:互聯網
上載者:User

標籤:

三種IPC這就是所謂的XSI IPC,每間:
  • 訊息佇列
  • 訊號量
  • 共用儲存空間
以下分別介紹三種IPC的使用方法。
1、訊息佇列訊息佇列是訊息的連結資料表,具有例如以下函數介面:
  • msgget:建立一個新隊列或開啟一個現存的隊列。
  • msgsnd:將訊息加入到隊列尾端。
  • msgrcv:從隊列中取訊息。
我們能夠自行定義一個表示訊息的結構體,它由類型欄位和實際資料群組成:
struct mest_t {    long type;          // 訊息類型    char text[512];     // 訊息內容};


有了訊息類型。當我們用msgrcv函數取訊息時,就不一定要以先進先出的順序,而是能夠依據訊息類型取訊息了。以下是一段簡單的測試代碼:
#include <stdio.h>#include <sys/msg.h>#include <sys/types.h>#include <string.h>#include <errno.h> struct mest_t {    long type;    char text[512];}; int main(void){    pid_t pid;    int mq_id;    struct mest_t msg;     /* IPC_PRIVATE用於建立一個新隊列     * 設定了IPC_EXCL而且設定了IPC_CREAT。當檔案存在時返回錯誤     */    mq_id = msgget(IPC_PRIVATE, IPC_CREAT | IPC_EXCL);    if (mq_id == EEXIST)        return -1;  /* 返回EEXIST表示IPC已存在 */     if ((pid = fork()) < 0)        return -1;    else if (pid == 0)    {        /* 子進程 */        msg.type = 123;                     /* 訊息類型 */        strcpy(msg.text, "Hello world!");   /* 訊息內容 */         /* 非堵塞方式將訊息放入訊息佇列         * 隊列已滿則返回EAGAIN         */        while (msgsnd(mq_id, (long *)&msg, 512, IPC_NOWAIT) == EAGAIN)            sleep(1);    }    else    {        /* 非堵塞方式從隊列中取訊息         * 假設沒有指定類型的訊息。函數返回-1,errno設定為ENOMSG         */        while (msgrcv(mq_id, (long *)&msg, 512, 123, IPC_NOWAIT) == -1)        {            if (errno == ENOMSG)            {                printf("There is no this type message!\n");                sleep(1);            }        }         printf("%s\n", msg.text);    }      return 0;}


當父進程須要取的訊息類型和子進程發送的訊息類型同樣時。執行結果例如以下:

父進程可以非常快接收到子進程發送到訊息佇列中的訊息。

可是改動msgrcv的訊息類型參數後,執行結果例如以下:

父進程得不到想要的訊息,一直列印錯誤資訊。
2、訊號量訊號量是一個計數器。用於多進程對共用資料對象的訪問。步驟例如以下:

  • 測試控制該資源的訊號量。
  • 若此訊號量的值為正。則進程能夠使用該資源。進程將訊號量值減1,表示它使用了一個資源單位。
  • 若此訊號量的值為0。則進程進入休眠狀態,直至訊號量大於0。進程被喚醒後。它返回至第一步。
當進程不再使用由一個訊號量控制的共用資源時,該訊號量值增1。假設有進程正在休眠等待此訊號量,則喚醒它們。
3、共用儲存共用儲存同意多個進程共用一塊給定的儲存區。是最快的一種IPC。測試代碼例如以下:
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/shm.h> #define SHM_SIZE 100#define SHM_MODE (SHM_W | SHM_R |  IPC_CREAT) int main(){    int shmid;    char *shmptr;    pid_t pid;     /* 獲得共用儲存標識符 */    if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0)        return -1;     if ((pid = fork()) < 0)        return -1;    else if (pid == 0)    {        shmptr = shmat(shmid, 0, 0);    /* 參數2為0表示由核心分配共用空間 */        printf("Child attached shared memory is : %lx\n", (unsigned long)shmptr);        shmdt(shmptr);                  /* 使進程脫離該共用空間 */    }    else    {        waitpid(pid, NULL, 0);         shmptr = shmat(shmid, 0, 0);        printf("Parent attached shared memory is : %lx\n", (unsigned long)shmptr);        shmdt(shmptr);         shmctl(shmid, IPC_RMID, 0);  /* 刪除該共用儲存段 */    }     return 0;}


執行結果:

從上面的實驗結果能夠看出,父、子進程共用了同一個儲存段。

有一點須要注意,shmdt函數僅僅是讓進程脫離該共用儲存段,但該儲存段依舊存在而且shmid依舊有效。它是與shmat相相應的。而還有一個函數shmctl使用IPC_RMID參數時才是真正刪除該共用段。
共用儲存段和儲存映射I/O中的mmap函數很相似,它們之間的差別是:mmap映射的儲存段是與檔案相關聯的,XSI共用儲存段則並無這樣的關聯。
參考:《unix編程環境》 P415-P432.

【Linux計劃】XSI IPC

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.