進程間通信

1.信號

信號是比較復雜的通信方式,用于通知接收進程有某種事情發生,除了用于進程間通信外,進程還可以發送信號給進程本身;linux除了支持Unix早期信息語義函數signal外,還支持語義符合Posix 1標準的信號函數sigaction。

  • signal() 告訴系統內核怎么處理該信號
  • sigaction() 也是處理信號,但比signal更健壯
  • kill() 發送信號
  • alarm() 經過預定時間后發送SIGALARM信號

2.mmap文件映射:

也是一種共享內存,但是它是直接映射到磁盤中具體的文件,會涉及到磁盤的讀寫和io占用,不如shm共享內存效率高,但因為它的實際存儲并沒有反映到內存上,可以申請比較大的存儲空間。

3.管道及有名管道

管道可用于具有親緣關系進程間的通信,例如父子進程,但是有名管道允許無關系的進程間通信。管道其實就是建立一個FIFO文件,一個進程往里面寫數據,另外的進程讀取數據。
demo如下:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/wait.h>
    #include <stdlib.h>

    void sys_err(const char *str)
    {
        perror(str);
        exit(1);
    }

    int main()
    {
        pid_t pid;
        char buf[1024];
        int fd[2];
        char *p = "test for pipe\n";
        if (pipe(fd) == -1)
            sys_err("pipe");

        pid = fork();
        if (pid < 0) 
        {
            sys_err("fork err");
        }
        else if(pid == 0)
        {
            //父進程   
            close(fd[1]);
            int len = read(fd[0], buf, sizeof(buf));
            write(STDOUT_FILENO, buf, len);  //輸出到屏幕
            close(fd[0]);
        }
        else
        {
            //子進程
            close(fd[0]);
            write(fd[1], p, strlen(p)); //寫入test for pipe
            wait(NULL);
            close(fd[1]);
        }

        return 0;
    }

4.消息隊列

消息隊列也叫報文隊列,消息隊列是消息的鏈接表,包括Posix消息隊列和SystemV消息隊列,有足夠權限的進程可以向隊列中添加消息,被賦予讀權限的進程則可以讀走隊列中的信息,消息隊列克服了信號承載信息量少,管道只能承載無格式字節流以及緩沖區大小受限等缺點。
發送消息demo如下:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct my_msg_st
{
    long int my_msg_type;
    char some_text[BUFSIZ];
};

int main(void)
{
    int running = 1;
    struct my_msg_st some_data;
    int msgid = 0;
    char buffer[BUFSIZ] = {0};
    memset((void*)&some_data, 0, sizeof(some_data));

    /*創建消息隊列*/
    msgid=msgget((key_t)1234,0666 | IPC_CREAT);
    if(msgid==-1)
    {
        fprintf(stderr,"msgget failed with error:%d\n",errno);
        exit(EXIT_FAILURE);
    }

    /*循環向消息隊列中添加消息*/
    while(running)
    {
        memset(buffer, 0, sizeof(buffer));
        printf("Enter some text:");
        fgets(buffer,BUFSIZ,stdin);
        some_data.my_msg_type=1;
        strcpy(some_data.some_text,buffer);

        /*添加消息*/
        if(msgsnd(msgid,(void *)&some_data,BUFSIZ,0)==-1)
        {
            fprintf(stderr,"msgsed failed\n");
            exit(EXIT_FAILURE);
        }

        /*用戶輸入的為“end”時結束循環*/
        if(strncmp(buffer,"end",3)==0)
        {
            running=0;
        }
    }
    exit(EXIT_SUCCESS);
}
接收消息demo如下:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct my_msg_st
{
    long int my_msg_type;
    char some_text[BUFSIZ];
};

int main(void)
{
    int running=1;
    int msgid = 0;
    struct my_msg_st some_data;
    long int msg_to_receive=0;
    memset((void*)&some_data, 0, sizeof(some_data));

    /*創建消息隊列*/
    msgid=msgget((key_t)1234,0666 | IPC_CREAT);
    if(msgid==-1)
    {
        fprintf(stderr,"msgget failed with error: %d\n",errno);
        exit(EXIT_FAILURE);
    }
    
    /*循環從消息隊列中接收消息*/
    while(running)
    {
        /*讀取消息*/
        if(msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)==-1)
        {
            fprintf(stderr,"msgrcv failed with error: %d\n",errno);
            exit(EXIT_FAILURE);
        }

        printf("接收到的消息為: %s",some_data.some_text);

        /*接收到的消息為“end”時結束循環*/
        if(strncmp(some_data.some_text,"end",3) == 0)
        {
            running=0;
        }
    }

    /*從系統內核中移走消息隊列*/
    if(msgctl(msgid,IPC_RMID,0) == -1)
    {
        fprintf(stderr,"msgctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

5.共享內存
共享內存是一種文件映射,使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其他通信機制,如信號量結合使用,來達到進程間的同步及互斥。
demo如下:
寫入共享內存:

#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<string.h>
#include<errno.h>

typedef struct _Teacher
{
    char name[64];
    int age;
}Teacher;

int main(int argc, char *argv[])
{
    int ret = 0;
    int    shmid = 0;
    //創建共享內存 ,相當于打開文件,文件不存在則創建
    shmid = shmget(0x2234, sizeof(Teacher), IPC_CREAT | 0666); 
    if (shmid == -1)
    {
        perror("shmget err");
        return errno;
    }
    printf("shmid:%d \n", shmid);
    Teacher *p = NULL;
    //將共享內存段連接到進程地址空間
    p = (Teacher*)shmat(shmid, NULL, 0);//第二個參數shmaddr為NULL,核心自動選擇一個地址
    if (p == (void *)-1 )
    {
        perror("shmget err");
        return errno;
    }
    strcpy(p->name, "aaaa");
    p->age = 33;
    //將共享內存段與當前進程脫離
    shmdt(p);
        
    printf("鍵入1 刪除共享內存,其他不刪除\n");
    
    int num = 0;
    scanf("%d", &num);
    if (num == 1)
    {
        //用于控制共享內存
        ret = shmctl(shmid, IPC_RMID, NULL);//IPC_RMID為刪除內存段
        if (ret < 0)
        {
            perror("rmerrr\n");
        }
    }                 

    return 0;    
}
從共享內存讀取:

#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<string.h>
#include<errno.h>

typedef struct _Teacher
{
    char name[64];
    int age;
}Teacher;

int main(int argc, char *argv[])
{
    int ret = 0;
    int    shmid = 0;
    //打開獲取共享內存
    shmid = shmget(0x2234, 0, 0); 
    if (shmid == -1)
    {
        perror("shmget err");
        return errno;
    }
    printf("shmid:%d \n", shmid);
    Teacher *p = NULL;
    //將共享內存段連接到進程地址空間
    p = (Teacher*)shmat(shmid, NULL, 0);
    if (p == (void *)-1 )
    {
        perror("shmget err");
        return errno;
    }
    
    printf("name:%s\n", p->name);
    printf("age:%d \n", p->age);
    //將共享內存段與當前進程脫離
    shmdt(p);
    
    printf("鍵入1 程序暫停,其他退出\n");
    
    while(1)
    {
        sleep(1);
    }       
    return 0;
}

6.socket
socket也就是套接字,最普遍的進程間通信機制,可用于不同機器之間的進程間通信,具體見網絡編程。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容