国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Linux進(jìn)程間通信的方式

發(fā)布時(shí)間:2021-08-23 15:02 來(lái)源:億速云 閱讀:0 作者:chen 欄目: 服務(wù)器 歡迎投稿:712375056

這篇文章主要介紹“Linux進(jìn)程間通信的方式”,在日常操作中,相信很多人在Linux進(jìn)程間通信的方式問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對大家解答”Linux進(jìn)程間通信的方式”的疑惑有所幫助!接下來(lái),請跟著(zhù)小編一起來(lái)學(xué)習吧!

下面將講解進(jìn)程間通信的另一種方式,使用共享內存。

一、什么是共享內存

顧名思義,共享內存就是允許兩個(gè)不相關(guān)的進(jìn)程訪(fǎng)問(wèn)同一個(gè)邏輯內存。共享內存是在兩個(gè)正在運行的進(jìn)程之間共享和傳遞數據的一種非常有效的方式。不同進(jìn)程之間共享的內存通常安排為同一段物理內存。進(jìn)程可以將同一段共享內存連接到它們自己的地址空間中,所有進(jìn)程都可以訪(fǎng)問(wèn)共享內存中的地址,就好像它們是由用C語(yǔ)言函數malloc分配的內存一樣。而如果某個(gè)進(jìn)程向共享內存寫(xiě)入數據,所做的改動(dòng)將立即影響到可以訪(fǎng)問(wèn)同一段共享內存的任何其他進(jìn)程。

特別提醒:共享內存并未提供同步機制,也就是說(shuō),在***個(gè)進(jìn)程結束對共享內存的寫(xiě)操作之前,并無(wú)自動(dòng)機制可以阻止第二個(gè)進(jìn)程開(kāi)始對它進(jìn)行讀取。所以我們通常需要用其他的機制來(lái)同步對共享內存的訪(fǎng)問(wèn),例如前面說(shuō)到的信號量。有關(guān)信號量的更多內容,可以查閱我的另一篇文章:Linux進(jìn)程間通信——使用信號量

二、共享內存的使得

與信號量一樣,在Linux中也提供了一組函數接口用于使用共享內存,而且使用共享共存的接口還與信號量的非常相似,而且比使用信號量的接口來(lái)得簡(jiǎn)單。它們聲明在頭文件 sys/shm.h中。

1、shmget函數

該函數用來(lái)創(chuàng )建共享內存,它的原型為:

[cpp] view plain copy   int shmget(key_t key, size_t size, int shmflg);

***個(gè)參數,與信號量的semget函數一樣,程序需要提供一個(gè)參數key(非0整數),它有效地為共享內存段命名,shmget函數成功時(shí)返回一個(gè)與key相關(guān)的共享內存標識符(非負整數),用于后續的共享內存函數。調用失敗返回-1.

不相關(guān)的進(jìn)程可以通過(guò)該函數的返回值訪(fǎng)問(wèn)同一共享內存,它代表程序可能要使用的某個(gè)資源,程序對所有共享內存的訪(fǎng)問(wèn)都是間接的,程序先通過(guò)調用shmget函數并提供一個(gè)鍵,再由系統生成一個(gè)相應的共享內存標識符(shmget函數的返回值),只有shmget函數才直接使用信號量鍵,所有其他的信號量函數使用由semget函數返回的信號量標識符。

第二個(gè)參數,size以字節為單位指定需要共享的內存容量

第三個(gè)參數,shmflg是權限標志,它的作用與open函數的mode參數一樣,如果要想在key標識的共享內存不存在時(shí),創(chuàng )建它的話(huà),可以與IPC_CREAT做或操作。共享內存的權限標志與文件的讀寫(xiě)權限一樣,舉例來(lái)說(shuō),0644,它表示允許一個(gè)進(jìn)程創(chuàng )建的共享內存被內存創(chuàng )建者所擁有的進(jìn)程向共享內存讀取和寫(xiě)入數據,同時(shí)其他用戶(hù)創(chuàng )建的進(jìn)程只能讀取共享內存。

2、shmat函數

***次創(chuàng )建完共享內存時(shí),它還不能被任何進(jìn)程訪(fǎng)問(wèn),shmat函數的作用就是用來(lái)啟動(dòng)對該共享內存的訪(fǎng)問(wèn),并把共享內存連接到當前進(jìn)程的地址空間。它的原型如下:

[cpp] view plain copy   void *shmat(int shm_id, const void *shm_addr, int shmflg);

***個(gè)參數,shm_id是由shmget函數返回的共享內存標識。

第二個(gè)參數,shm_addr指定共享內存連接到當前進(jìn)程中的地址位置,通常為空,表示讓系統來(lái)選擇共享內存的地址。

第三個(gè)參數,shm_flg是一組標志位,通常為0。

調用成功時(shí)返回一個(gè)指向共享內存***個(gè)字節的指針,如果調用失敗返回-1.

3、shmdt函數

該函數用于將共享內存從當前進(jìn)程中分離。注意,將共享內存分離并不是刪除它,只是使該共享內存對當前進(jìn)程不再可用。它的原型如下:

[cpp] view plain copy   int shmdt(const void *shmaddr);

參數shmaddr是shmat函數返回的地址指針,調用成功時(shí)返回0,失敗時(shí)返回-1.

4、shmctl函數

與信號量的semctl函數一樣,用來(lái)控制共享內存,它的原型如下:

[cpp] view plain copy   int shmctl(int shm_id, int command, struct shmid_ds *buf);

***個(gè)參數,shm_id是shmget函數返回的共享內存標識符。

第二個(gè)參數,command是要采取的操作,它可以取下面的三個(gè)值 :

  • IPC_STAT:把shmid_ds結構中的數據設置為共享內存的當前關(guān)聯(lián)值,即用共享內存的當前關(guān)聯(lián)值覆蓋shmid_ds的值。

  • IPC_SET:如果進(jìn)程有足夠的權限,就把共享內存的當前關(guān)聯(lián)值設置為shmid_ds結構中給出的值

  • IPC_RMID:刪除共享內存段 

第三個(gè)參數,buf是一個(gè)結構指針,它指向共享內存模式和訪(fǎng)問(wèn)權限的結構。

shmid_ds結構至少包括以下成員: 

[cpp] view plain copy   struct shmid_ds    {        uid_t shm_perm.uid;        uid_t shm_perm.gid;        mode_t shm_perm.mode;    };

三、使用共享內存進(jìn)行進(jìn)程間通信

說(shuō)了這么多,又到了實(shí)戰的時(shí)候了。下面就以?xún)蓚€(gè)不相關(guān)的進(jìn)程來(lái)說(shuō)明進(jìn)程間如何通過(guò)共享內存來(lái)進(jìn)行通信。其中一個(gè)文件shmread.c創(chuàng )建共享內存,并讀取其中的信息,另一個(gè)文件shmwrite.c向共享內存中寫(xiě)入數據。為了方便操作和數據結構的統一,為這兩個(gè)文件定義了相同的數據結構,定義在文件shmdata.c中。結構shared_use_st中的written作為一個(gè)可讀或可寫(xiě)的標志,非0:表示可讀,0表示可寫(xiě),text則是內存中的文件。

shmdata.h的源代碼如下:

[cpp] view plain copy   #ifndef _SHMDATA_H_HEADER    #define _SHMDATA_H_HEADER      #define TEXT_SZ 2048      struct shared_use_st    {        int written;//作為一個(gè)標志,非0:表示可讀,0表示可寫(xiě)        char text[TEXT_SZ];//記錄寫(xiě)入和讀取的文本    };      #endif

源文件shmread.c的源代碼如下: 

[cpp] view plain copy   #include <unistd.h>    #include <stdlib.h>    #include <stdio.h>    #include <sys/shm.h>    #include "shmdata.h"      int main()    {        int running = 1;//程序是否繼續運行的標志        void *shm = NULL;//分配的共享內存的原始首地址        struct shared_use_st *shared;//指向shm        int shmid;//共享內存標識符        //創(chuàng  )建共享內存        shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);        if(shmid == -1)        {            fprintf(stderr, "shmget failed\n");            exit(EXIT_FAILURE);        }        //將共享內存連接到當前進(jìn)程的地址空間        shm = shmat(shmid, 0, 0);        if(shm == (void*)-1)        {            fprintf(stderr, "shmat failed\n");            exit(EXIT_FAILURE);        }        printf("\nMemory attached at %X\n", (int)shm);        //設置共享內存        shared = (struct shared_use_st*)shm;        shared->written = 0;        while(running)//讀取共享內存中的數據        {            //沒(méi)有進(jìn)程向共享內存定數據有數據可讀取            if(shared->written != 0)            {                printf("You wrote: %s", shared->text);                sleep(rand() % 3);                //讀取完數據,設置written使共享內存段可寫(xiě)                shared->written = 0;                //輸入了end,退出循環(huán)(程序)                if(strncmp(shared->text, "end", 3) == 0)                    running = 0;            }            else//有其他進(jìn)程在寫(xiě)數據,不能讀取數據                sleep(1);        }        //把共享內存從當前進(jìn)程中分離        if(shmdt(shm) == -1)        {            fprintf(stderr, "shmdt failed\n");            exit(EXIT_FAILURE);        }        //刪除共享內存        if(shmctl(shmid, IPC_RMID, 0) == -1)        {            fprintf(stderr, "shmctl(IPC_RMID) failed\n");            exit(EXIT_FAILURE);        }        exit(EXIT_SUCCESS);    }

源文件shmwrite.c的源代碼如下:

[cpp] view plain copy   #include <unistd.h>    #include <stdlib.h>    #include <stdio.h>    #include <string.h>    #include <sys/shm.h>    #include "shmdata.h"      int main()    {        int running = 1;        void *shm = NULL;        struct shared_use_st *shared = NULL;        char buffer[BUFSIZ + 1];//用于保存輸入的文本        int shmid;        //創(chuàng  )建共享內存        shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);        if(shmid == -1)        {            fprintf(stderr, "shmget failed\n");            exit(EXIT_FAILURE);        }        //將共享內存連接到當前進(jìn)程的地址空間        shm = shmat(shmid, (void*)0, 0);        if(shm == (void*)-1)        {            fprintf(stderr, "shmat failed\n");            exit(EXIT_FAILURE);        }        printf("Memory attached at %X\n", (int)shm);        //設置共享內存        shared = (struct shared_use_st*)shm;        while(running)//向共享內存中寫(xiě)數據        {            //數據還沒(méi)有被讀取,則等待數據被讀取,不能向共享內存中寫(xiě)入文本            while(shared->written == 1)            {                sleep(1);                printf("Waiting...\n");            }            //向共享內存中寫(xiě)入數據            printf("Enter some text: ");            fgets(buffer, BUFSIZ, stdin);            strncpy(shared->text, buffer, TEXT_SZ);            //寫(xiě)完數據,設置written使共享內存段可讀            shared->written = 1;            //輸入了end,退出循環(huán)(程序)            if(strncmp(buffer, "end", 3) == 0)                running = 0;        }        //把共享內存從當前進(jìn)程中分離        if(shmdt(shm) == -1)        {            fprintf(stderr, "shmdt failed\n");            exit(EXIT_FAILURE);        }        sleep(2);        exit(EXIT_SUCCESS);    }

再來(lái)看看運行的結果:

分析:

1、程序shmread創(chuàng )建共享內存,然后將它連接到自己的地址空間。在共享內存的開(kāi)始處使用了一個(gè)結構struct_use_st。該結構中有個(gè)標志written,當共享內存中有其他進(jìn)程向它寫(xiě)入數據時(shí),共享內存中的written被設置為0,程序等待。當它不為0時(shí),表示沒(méi)有進(jìn)程對共享內存寫(xiě)入數據,程序就從共享內存中讀取數據并輸出,然后重置設置共享內存中的written為0,即讓其可被shmwrite進(jìn)程寫(xiě)入數據。

2、程序shmwrite取得共享內存并連接到自己的地址空間中。檢查共享內存中的written,是否為0,若不是,表示共享內存中的數據還沒(méi)有被完,則等待其他進(jìn)程讀取完成,并提示用戶(hù)等待。若共享內存的written為0,表示沒(méi)有其他進(jìn)程對共享內存進(jìn)行讀取,則提示用戶(hù)輸入文本,并再次設置共享內存中的written為1,表示寫(xiě)完成,其他進(jìn)程可對共享內存進(jìn)行讀操作。

四、關(guān)于前面的例子的安全討論

這個(gè)程序是不安全的,當有多個(gè)程序同時(shí)向共享內存中讀寫(xiě)數據時(shí),問(wèn)題就會(huì )出現??赡苣銜?huì )認為,可以改變一下written的使用方式,例如,只有當written為0時(shí)進(jìn)程才可以向共享內存寫(xiě)入數據,而當一個(gè)進(jìn)程只有在written不為0時(shí)才能對其進(jìn)行讀取,同時(shí)把written進(jìn)行加1操作,讀取完后進(jìn)行減1操作。這就有點(diǎn)像文件鎖中的讀寫(xiě)鎖的功能。咋看之下,它似乎能行得通。但是這都不是原子操作,所以這種做法是行不能的。試想當written為0時(shí),如果有兩個(gè)進(jìn)程同時(shí)訪(fǎng)問(wèn)共享內存,它們就會(huì )發(fā)現written為0,于是兩個(gè)進(jìn)程都對其進(jìn)行寫(xiě)操作,顯然不行。當written為1時(shí),有兩個(gè)進(jìn)程同時(shí)對共享內存進(jìn)行讀操作時(shí)也是如些,當這兩個(gè)進(jìn)程都讀取完是,written就變成了-1。 

要想讓程序安全地執行,就要有一種進(jìn)程同步的進(jìn)制,保證在進(jìn)入臨界區的操作是原子操作。例如,可以使用前面所講的信號量來(lái)進(jìn)行進(jìn)程的同步。因為信號量的操作都是原子性的。

五、使用共享內存的優(yōu)缺點(diǎn)

1、優(yōu)點(diǎn):我們可以看到使用共享內存進(jìn)行進(jìn)程間的通信真的是非常方便,而且函數的接口也簡(jiǎn)單,數據的共享還使進(jìn)程間的數據不用傳送,而是直接訪(fǎng)問(wèn)內存,也加快了程序的效率。同時(shí),它也不像匿名管道那樣要求通信的進(jìn)程有一定的父子關(guān)系。

2、缺點(diǎn):共享內存沒(méi)有提供同步的機制,這使得我們在使用共享內存進(jìn)行進(jìn)程間通信時(shí),往往要借助其他的手段來(lái)進(jìn)行進(jìn)程間的同步工作。

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

久久天天躁狠狠躁夜夜96流白浆| 夜夜天天噜狠狠爱2019| 9I国产麻豆国产AV旗袍| 国精产品一区一区二区三区MBA| 伊人久久大香线蕉AV色婷婷色| 一本一本久久aa综合精品 |