進程通訊 IPC 之訊息佇列

來源:互聯網
上載者:User

/**
 *IPC是指進程間的通訊,其中有三種我們稱之為IPC即訊息佇列、訊號量以及共用儲存空間
 *建立IPC結構(調用msgget\semget\shmget), 應指定一個鍵,鍵的資料類型是基本系統資料類型key_t,鍵由核心變換成標識符
 *以下是訊息佇列msgget
 */
/**
 * 優缺點:IPC結構是在系統範圍內起作用的,沒有訪問計數。例如,如果進程建立了一個訊息佇列,在該隊列中放入了幾則訊息,
 * 然後終止,但是該訊息佇列及其內容並不會被刪除,它們餘留在系統中直至出現下述情況:
 * 由某個進程調用msgrcv或msgctl讀取訊息或刪除訊息佇列,或某個進程執行ipcrm命令刪除訊息佇列,
 * 或由正在再啟動的系統刪除訊息佇列,將此與管道相比,當最後一個訪問管道的進程終止時,管道就被完全地刪除了。
 * 對於FIFO而言,雖然當最後一個引用FIFO進程終止時其名字仍保留在系統中,直至顯式地刪除它,但是留在FIFO中的資料卻在此時被全部刪除,於是也就徒有虛名了。
 * XSI IPC的另一個問題是這些IPC結構在檔案系統中沒有名字,我們不能使用那些使用檔案系統的函數來訪問它們或修改他們的屬性。
 * 為了支援它們不得不增加了十幾條全新的系統調用(msgget,semop,shmat).我們不能用ls命令見到IPC對象,不能用rm命令刪除他們,
 * 不能用chmod命令修改它們的存取權限。於是就不得不增加新的命令ipcs和ipcrm.
 */
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>

#define MY_KEY 8800811           // need to change

#define SERVER_ID 2

#define MAX_BUF 200
void sigend(int);

//訊息結構體
struct mymsg {
    long mtype;
    long pid;
    char buf[MAX_BUF]; //在此指定了共用記憶體的大小 = MAX_BUF+ 8
};

int msgid;

bool isWorking = true;

#define SERVER_TYPE 5555
#define CLIENT_TYPE 6666

//阻塞式接收資料
void * RunRecvData(void * pVoid)
{
    //指定接收類型--對應 發送結構體mymsg.mtype內容
    long *typ = (long*)pVoid;

    struct mymsg msgbuf;

    while(isWorking)
    {
        //接收訊息;
        msgrcv(msgid, &msgbuf, sizeof(struct mymsg), *typ, 0);

        printf("recv data: %s, type=%ld, pid= %ld \n", msgbuf.buf, msgbuf.mtype, msgbuf.pid);
    }

    return NULL;
}

int main3(void)
{
    pthread_t pidRecv;

    struct mymsg msgbuf; //定義一結構變數
    //建立新的訊息佇列
    if ((msgid = msgget(MY_KEY, IPC_CREAT | IPC_EXCL | 0666)) < 0)
    {
        //建立失敗,已經存在,直接擷取訊息id,擷取已有的訊息佇列
        msgid = msgget(MY_KEY, 0666);

        printf("Act as client, ask question and wait answer! msgid=%d\n", msgid);

        printf("To end this process, enter end as input question.\n\n");

        pid_t pid = getpid();

        long type = SERVER_TYPE;

        pthread_create(&pidRecv,NULL,RunRecvData,&type);

        //I/O中斷
        printf("Input question in one line:\n");
        fgets(msgbuf.buf, sizeof(struct mymsg) - 2 * sizeof(long) - 1, stdin);

        while (strcmp(msgbuf.buf, "end\n"))
        {
            //獲得服務進程號
            msgbuf.mtype = CLIENT_TYPE;// SERVER_ID;
            //獲得當前進程的進程號
            msgbuf.pid = getpid();
            //發送訊息;
            msgsnd(msgid, &msgbuf, sizeof(struct mymsg) - sizeof(long), 0);

            printf("Input question in one line:\n");

            memset(msgbuf.buf,0,sizeof(msgbuf.buf));

            fgets(msgbuf.buf, sizeof(struct mymsg) - 2 * sizeof(long) - 1,
                    stdin);
        }
    }
    else
    {
        //設定某一訊號的對應動作, sigend 刪除標記
        signal(SIGINT, sigend);
        signal(SIGTERM, sigend);

        printf("ACT SERVER!!! Wait question and give answer. msgid=%d\n", msgid);
        printf("To end this process, try Ctrl+C or use kill.\n\n");

        long tmpId = CLIENT_TYPE;

        pthread_create(&pidRecv,NULL,RunRecvData,&tmpId);

        while (1)
        {
            memset(msgbuf.buf,0,sizeof(msgbuf.buf));
            fgets(msgbuf.buf, sizeof(struct mymsg) - 2 * sizeof(long) - 1,
                    stdin);

            msgbuf.mtype = SERVER_TYPE; //msgbuf.pid;
            msgbuf.pid = getpid();
            //發送訊息;
            msgsnd(msgid, &msgbuf, sizeof(struct mymsg) - sizeof(long), 0);
        }
    }
}

void sigend(int sig)
{
    //操縱一個訊息佇列;
    //IPC_RMID:從系統核心中移走訊息佇列。
    //IPC_STAT:讀取訊息佇列的資料結構msqid_ds,並將其儲存在buf指定的地址中。 可以直接拷貝,減少記憶體複製
    //IPC_SET:設定訊息佇列的資料結構msqid_ds中的ipc_perm元素的值。這個值取自buf參數。
    if(0==msgctl(msgid, IPC_RMID, 0))
        printf("msgctl:success\n");
    else{
        //列印錯誤資訊
    }
    exit(0);
}

聯繫我們

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