成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

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

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

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

成都創(chuàng)新互聯(lián)公司的客戶來自各行各業(yè),為了共同目標(biāo),我們在工作上密切配合,從創(chuàng)業(yè)型小企業(yè)到企事業(yè)單位,感謝他們對我們的要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。專業(yè)領(lǐng)域包括網(wǎng)站設(shè)計制作、網(wǎng)站建設(shè)、電商網(wǎng)站開發(fā)、微信營銷、系統(tǒng)平臺開發(fā)。

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

一、什么是共享內(nèi)存

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

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

二、共享內(nèi)存的使得

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

1、shmget函數(shù)

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

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

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

不相關(guān)的進(jìn)程可以通過該函數(shù)的返回值訪問同一共享內(nèi)存,它代表程序可能要使用的某個資源,程序?qū)λ泄蚕韮?nèi)存的訪問都是間接的,程序先通過調(diào)用shmget函數(shù)并提供一個鍵,再由系統(tǒng)生成一個相應(yīng)的共享內(nèi)存標(biāo)識符(shmget函數(shù)的返回值),只有shmget函數(shù)才直接使用信號量鍵,所有其他的信號量函數(shù)使用由semget函數(shù)返回的信號量標(biāo)識符。

第二個參數(shù),size以字節(jié)為單位指定需要共享的內(nèi)存容量

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

2、shmat函數(shù)

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

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

***個參數(shù),shm_id是由shmget函數(shù)返回的共享內(nèi)存標(biāo)識。

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

第三個參數(shù),shm_flg是一組標(biāo)志位,通常為0。

調(diào)用成功時返回一個指向共享內(nèi)存***個字節(jié)的指針,如果調(diào)用失敗返回-1.

3、shmdt函數(shù)

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

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

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

4、shmctl函數(shù)

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

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

***個參數(shù),shm_id是shmget函數(shù)返回的共享內(nèi)存標(biāo)識符。

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

IPC_STAT:把shmid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為共享內(nèi)存的當(dāng)前關(guān)聯(lián)值,即用共享內(nèi)存的當(dāng)前關(guān)聯(lián)值覆蓋shmid_ds的值。

IPC_SET:如果進(jìn)程有足夠的權(quán)限,就把共享內(nèi)存的當(dāng)前關(guān)聯(lián)值設(shè)置為shmid_ds結(jié)構(gòu)中給出的值

IPC_RMID:刪除共享內(nèi)存段 

第三個參數(shù),buf是一個結(jié)構(gòu)指針,它指向共享內(nèi)存模式和訪問權(quán)限的結(jié)構(gòu)。

shmid_ds結(jié)構(gòu)至少包括以下成員: 

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

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

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

shmdata.h的源代碼如下:

[cpp] view plain copy   #ifndef _SHMDATA_H_HEADER    #define _SHMDATA_H_HEADER      #define TEXT_SZ 2048      struct shared_use_st    {        int written;//作為一個標(biāo)志,非0:表示可讀,0表示可寫        char text[TEXT_SZ];//記錄寫入和讀取的文本    };      #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;//程序是否繼續(xù)運行的標(biāo)志        void *shm = NULL;//分配的共享內(nèi)存的原始首地址        struct shared_use_st *shared;//指向shm        int shmid;//共享內(nèi)存標(biāo)識符        //創(chuàng)建共享內(nèi)存        shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);        if(shmid == -1)        {            fprintf(stderr, "shmget failed\n");            exit(EXIT_FAILURE);        }        //將共享內(nèi)存連接到當(dāng)前進(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);        //設(shè)置共享內(nèi)存        shared = (struct shared_use_st*)shm;        shared->written = 0;        while(running)//讀取共享內(nèi)存中的數(shù)據(jù)        {            //沒有進(jìn)程向共享內(nèi)存定數(shù)據(jù)有數(shù)據(jù)可讀取            if(shared->written != 0)            {                printf("You wrote: %s", shared->text);                sleep(rand() % 3);                //讀取完數(shù)據(jù),設(shè)置written使共享內(nèi)存段可寫                shared->written = 0;                //輸入了end,退出循環(huán)(程序)                if(strncmp(shared->text, "end", 3) == 0)                    running = 0;            }            else//有其他進(jìn)程在寫數(shù)據(jù),不能讀取數(shù)據(jù)                sleep(1);        }        //把共享內(nèi)存從當(dāng)前進(jìn)程中分離        if(shmdt(shm) == -1)        {            fprintf(stderr, "shmdt failed\n");            exit(EXIT_FAILURE);        }        //刪除共享內(nèi)存        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)建共享內(nèi)存        shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);        if(shmid == -1)        {            fprintf(stderr, "shmget failed\n");            exit(EXIT_FAILURE);        }        //將共享內(nèi)存連接到當(dāng)前進(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);        //設(shè)置共享內(nèi)存        shared = (struct shared_use_st*)shm;        while(running)//向共享內(nèi)存中寫數(shù)據(jù)        {            //數(shù)據(jù)還沒有被讀取,則等待數(shù)據(jù)被讀取,不能向共享內(nèi)存中寫入文本            while(shared->written == 1)            {                sleep(1);                printf("Waiting...\n");            }            //向共享內(nèi)存中寫入數(shù)據(jù)            printf("Enter some text: ");            fgets(buffer, BUFSIZ, stdin);            strncpy(shared->text, buffer, TEXT_SZ);            //寫完數(shù)據(jù),設(shè)置written使共享內(nèi)存段可讀            shared->written = 1;            //輸入了end,退出循環(huán)(程序)            if(strncmp(buffer, "end", 3) == 0)                running = 0;        }        //把共享內(nèi)存從當(dāng)前進(jìn)程中分離        if(shmdt(shm) == -1)        {            fprintf(stderr, "shmdt failed\n");            exit(EXIT_FAILURE);        }        sleep(2);        exit(EXIT_SUCCESS);    }

再來看看運行的結(jié)果:

分析:

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

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

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

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

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

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

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

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

分享文章:Linux進(jìn)程間通信的方式
鏈接分享:http://jinyejixie.com/article0/cghio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計公司Google、品牌網(wǎng)站制作、軟件開發(fā)、網(wǎng)站排名營銷型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司
南漳县| 武川县| 濮阳市| 县级市| 长岭县| 呼和浩特市| 家居| 瑞金市| 镇赉县| 陕西省| 资溪县| 阿图什市| 蓝田县| 尚义县| 新郑市| 甘谷县| 商洛市| 佛学| 宣化县| 珲春市| 佛山市| 弋阳县| 宣化县| 康乐县| 色达县| 桐梓县| 高唐县| 静安区| 天津市| 渭南市| 肇庆市| 盘锦市| 丰宁| 曲阜市| 庐江县| 河北省| 江西省| 越西县| 峨边| 友谊县| 南岸区|