日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux进程间的通信(C): 共享内存

發布時間:2023/12/2 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux进程间的通信(C): 共享内存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、共享內存介紹 共享內存是三個IPC(Inter-Process Communication)機制中的一個。 它允許兩個不相關的進程訪問同一個邏輯內存。 共享內存是在兩個正在進行的進程之間傳遞數據的一種非常有效的方式。 大多數的共享內存的實現, 都把由不同進程之間共享的內存安排為同一段物理內存
共享內存是由IPC為進程創建一個特殊的地址范圍, 它將出現在該進程的地址空間中。 其他進程可以將同一段共享內存連接它們自己的地址空間中。 所有進程都可以訪問共享內存中的地址, 就好像它們是由malloc分配的一樣。
如果某個進程向共享內存寫入了數據, 所做的改動將立刻被可以訪問同一段共享內存的任何其他進程看到。
二、共享內存的同步 共享內存為在多個進程之間共享和傳遞數據提供了一種有效的方式。 但是它并未提供同步機制 所以我們通常需要用其他的機制來同步對共享內存的訪問。 我們通常是用共享內存來提供對大塊內存區域的有效訪問, 同時通過傳遞小消息來同步對該內存的訪問。
在第一個進程結束對共享內存的寫操作之前, 并無自動的機制可以阻止第二個進程開始對它進行讀取。 對共享內存訪問的同步控制必須由程序員來負責。
下圖顯示了共享內存是如何共存的:
圖中的箭頭顯示了每個進程的邏輯地址空間到可用物理內存的映射關系。

三、共享內存使用的函數
  • #include?<sys/shm.h>

  • int?shmget(key_t key,?size_t size,?int?shmflg);
  • void?*shmat(int?shm_id,?const?void?*shm_addr,?int?shmflg);
  • int?shmdt(const?void?*shm_addr);
  • int?shmctl(int?shm_id,?int?cmd,?struct shmid_ds?*buf);

  • 1. shmget函數 該函數用來創建共享內存:
  • int shmget(key_t key, size_t size, int shmflg);
  • 參數: key : 和信號量一樣,程序需要提供一個參數key, ? ? ? 它有效地為共享內存段命名。 ? ? ?? ? ? ? 有一個特殊的鍵值IPC_PRIVATE,? ? ? ? 它用于創建一個只屬于創建進程的共享內存, ? ? ? 通常不會用到。 size: 以字節為單位指定需要共享的內存容量。 shmflag: 包含9個比特的權限標志, ? ? ? ? ?它們的作用與創建文件時使用的mode標志是一樣。 ? ? ? ? ?由IPC_CREAT定義的一個特殊比特必須和權限標志按位或 ? ? ? ? ?才能創建一個新的共享內存段。
    NOTE: 權限標志對共享內存非常有用, 因為它允許一個進程創建的共享內存可以被共享內存的創建者所擁有的進程寫入, 同時其它用戶創建的進程只能讀取共享內存。
    我們可以利用這個功能來提供一種有效的對數據進行只讀訪問的方法, 通過將數據放共享內存并設置它的權限, 就可以避免數據被其他用戶修改。
    返回值: 創建成功,則返回一個非負整數,即共享內存標識; 如果失敗,則返回-1.
    2. shmat函數 第一次創建共享內存段時,它不能被任何進程訪問。 要想啟動對該內存的訪問, 必須將其連接到一個進程的地址空間。 這個工作由shmat函數完成:
  • void?*shmat(int?shm_id,?const?void?*shm_addr,?int?shmflg);
  • 參數: shm_id : 由shmget返回的共享內存標識。 shm_add: 指定共享內存連接到當前進程中的地址位置。 ? ? ? ? ?它通常是一個空指針,? ? ? ? ? ?表示讓系統來選擇共享內存出現的地址。 shmflg : 是一組標志。 ? ? ? ? ?它的兩個可能取值是: ? ? ? ? ?SHM_RND, 和shm_add聯合使用, ? ? ? ? ? ? ? ? ? 用來控制共享內存連接的地址。 ? ? ? ? ?SHM_RDONLY, 它使連接的內存只讀 ? ? ? ? ? 返回值: 如果調用成功, 返回一個指向共享內存第一個字節的指針; 如果失敗,返回-1.
    共享內存的讀寫權限由它的屬主(共享內存的創建者), 它的訪問權限和當前進程的屬主決定。 共享內存的訪問權限類似于文件的訪問權限。
    3. shmdt 將共享內存從當前進程中分離。
  • int?shmdt(const?void?*shm_addr);
  • shm_addr: shmat返回的地址指針。
    成功時,返回0, 失敗時,返回-1.
    NOTE: 共享內存分離并未刪除它, 只是使得該共享內存對當前進程不再可用。
    4. shmctl 共享內存的控制函數
  • int?shmctl(int?shm_id,?int?cmd,?struct shmid_ds?*buf);
  • shmid_ds結構至少包含以下成員:
  • struct shmid_ds?{
  • ??uid_t shm_perm.uid;
  • ??uid_t shm_perm.gid;
  • ??mode_t shm_perm.mode;
  • }

  • 參數: shm_id : 是shmget返回的共享內存標識符。 command: 是要采取的動作, ? ? ? ? ?它可以取3個值:
    IPC_STAT??把shmid_ds結構中的數據設置為共享內存的當前關聯值 IPC_SET ??如果進程有足夠的權限, ? ? ? ? ? 就把共享內存的當前關聯值設置為shmid_ds結構中給出的值 IPC_RMID??刪除共享內存段
    buf ? ?: 是一個指針, ? ? ? ? ?包含共享內存模式和訪問權限的結構。
    返回值: 成功時,返回0, 失敗時,返回-1.
    四、示例 典型的消費者-生產者程序, 第一個程序(消費者)將創建一個共享內存段, 然后把寫到它里面的數據都顯示出來。 第二個程序(生產者)將連接一個已有的共享內存段, 并允許我們向其中輸入數據。
    shm_com.h
  • #define TEXT_SZ 2048

  • struct shared_use_st?{
  • ??int?written_by_you;
  • ??char some_text[TEXT_SZ];
  • };
  • 當有數據寫入這個結構中時, 我們用結構中的written_by_you標志來通知消費者。 需要傳輸的文本長度2K是隨意定的。
    shm1.c 消費者程序
  • #include?<unistd.h>
  • #include?<stdlib.h>
  • #include?<stdio.h>
  • #include?<string.h>

  • #include?<sys/shm.h>

  • #include?"shm_com.h"
  • int?main()
  • {
  • ??int?running?=?1;
  • ??void?*shared_memory?=?(void?*)0;
  • ??struct shared_use_st?*shared_stuff;
  • ??int?shmid;

  • ??srand((unsigned?int)getpid());
  • ??shmid?=?shmget((key_t)1234,?sizeof(struct shared_use_st),?0666?|?IPC_CREAT);

  • ??if?(shmid?==?-1)?{
  • ????fprintf(stderr,?"shmget failed\n");
  • ????exit(EXIT_FAILURE);
  • ??}

  • 現在,讓程序可以訪問這個共享內存:
  • ? shared_memory?=?shmat(shmid,?(void?*)0,?0);

  • ??if?(shared_memory?==?(void?*)-1)?{
  • ????fprintf(stderr,?"shmat failed\n");
  • ????exit(EXIT_FAILURE);
  • ??}

  • ??printf("Memory attached at %X\n",?(int)shared_memory);

  • 程序的下一部分將shared_memory分配給shared_stuff, 然后它輸出written_by_you中的文本。 循環將一直執行到在written_by_you中找到end字符串為止。 sleep調用強迫消費者程序在臨界區域多待一會, 讓生產者程序等待:
  • ? shared_stuff?=?(struct shared_use_st?*)shared_memory;
  • ??shared_stuff->written_by_you?=?0;

  • ??while(running)?
  • ? {
  • ????if?(shared_stuff->written_by_you)?
  • ? ? {
  • ??????printf("You wrote: %s",?shared_stuff->some_text);

  • ??????sleep(?rand()?%?4?);?/* make the other process wait for us ! */
  • ??????shared_stuff->written_by_you?=?0;

  • ??????if?(strncmp(shared_stuff->some_text,?“end”,?3)?==?0)?{
  • ????????running?=?0;
  • ??????}
  • ????}
  • ??}

  • 最后,共享內存被分離,然后被刪除:
  • ? if?(shmdt(shared_memory)?==?-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);
  • }
  • shm2.c 生產者程序 通過它向消費者程序輸入數據。
  • #include?<unistd.h>
  • #include?<stdlib.h>
  • #include?<stdio.h>
  • #include?<string.h>

  • #include?<sys/shm.h>

  • #include?"shm_com.h"

  • int?main()
  • {
  • ??int?running?=?1;
  • ??void?*shared_memory?=?(void?*)0;
  • ??struct shared_use_st?*shared_stuff;
  • ??char buffer[BUFSIZ];
  • ??int?shmid;

  • ??shmid?=?shmget((key_t)1234,?sizeof(struct shared_use_st),?0666?|?IPC_CREAT);
  • ??if?(shmid?==?-1)?
  • ? {
  • ????fprintf(stderr,?"shmget failed\n");
  • ????exit(EXIT_FAILURE);
  • ??}

  • ??shared_memory?=?shmat(shmid,?(void?*)0,?0);
  • ??if?(shared_memory?==?(void?*)-1)?
  • ? {
  • ????fprintf(stderr,?"shmat failed\n");
  • ????exit(EXIT_FAILURE);
  • ??}

  • ??printf("Memory attached at %X\n",?(int)shared_memory);

  • ??shared_stuff?=?(struct shared_use_st?*)shared_memory;
  • ??while(running)?
  • ? {
  • ????while(shared_stuff->written_by_you?==?1)?
  • ? ? {
  • ??????sleep(1);
  • ??????printf("waiting for client...\n");
  • ????}
  • ????printf("Enter some text: ");
  • ????fgets(buffer,?BUFSIZ,?stdin);

  • ????strncpy(shared_stuff->some_text,?buffer,?TEXT_SZ);
  • ????shared_stuff->written_by_you?=?1;

  • ????if?(strncmp(buffer,?"end",?3)?==?0)?{
  • ??????running?=?0;
  • ????}
  • ??}

  • ??if?(shmdt(shared_memory)?==?-1)?{
  • ????fprintf(stderr,?"shmdt failed\n");
  • ????exit(EXIT_FAILURE);
  • ??}

  • ??exit(EXIT_SUCCESS);
  • }

  • 運行程序, 將看到如下所示的樣本輸出:
  • $?./shm1?&
  • [1]?294
  • Memory attached at 40017000
  • $?./shm2
  • Memory attached at 40017000
  • Enter some text:?hello
  • You wrote:?hello
  • waiting?for?client...
  • waiting?for?client...
  • Enter some text:?
  • You wrote:?
  • waiting?for?client...
  • waiting?for?client...
  • waiting?for?client...
  • Enter some text:?end
  • You wrote:?end
  • $
  • 程序解析: 消費者程序 創建共享內存段, 然后將它連接到它自己的地址空間中, 并且, 我們在共享內存的開始處使用了一個結構shared_use_st. 該結構中有個標志written_by_you, 當共享內存中有數據寫入時,就設置這個標志。
    這個標志被設置時, 程序就從共享內存中讀取文本, 將它打印出來, 然后清除這個標志,表示已經讀完數據。 我們用一個特殊字符串end來退出循環。
    接下來, 程序分離共享內存段并刪除它。
    生產者程序 使用相同的鍵值1234來取得并連接同一個共享內存段, 然后提示用戶輸入一些文本。 如果標志written_by_you被設置, 生產者就知道消費都進程還未讀完上一次的數據, 因此就繼續等待。 當其它進程清除了這個標志后, 生產者寫入新的數據并設置這個標志。 它還使用字符串end來終止并分離共享內存段。
    這里提供的同步標志written_by_you, 它是一個非常缺乏效率的忙等待(不停地循環)。
    但在實際編程中, 應該使用信號量, 或通過傳遞消息(使用管道或IPC消息), 或生成信號 的方法來提供讀寫之間的更有效的同步機制。

    總結

    以上是生活随笔為你收集整理的linux进程间的通信(C): 共享内存的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 91精品久久香蕉国产线看观看 | 91福利视频网站 | 久久久永久久久人妻精品麻豆 | 91视频毛片 | av片一区二区三区 | 欧美123区 | 成人视频在线观看 | 97福利在线| 欧美人与性动交α欧美精品 | 97伊人| 一级做a免费 | 久久草网站 | 少妇xxxx69| 亚洲第一色在线 | 手机在线观看毛片 | 国产一在线 | 国产精品人人妻人人爽人人牛 | 91情侣在线 | 中文写幕一区二区三区免费观成熟 | 欧日韩不卡在线视频 | 精品视频一区二区三区四区五区 | 99嫩草| 久久99精品久久久久久国产越南 | 97久久人人超碰caoprom欧美 | 夜夜免费视频 | xxxwww18 | 手机在线免费看av | 在线日韩成人 | 国产精品观看 | 最新国产精品自拍 | 黑人巨大精品欧美一区二区蜜桃 | 奇米四色777 | 少妇一夜三次一区二区 | 欧美性猛交xxxx免费看久久久 | 欧美日韩一区二区电影 | 免费看欧美一级片 | 一级黄色网址 | 黄色大片在线播放 | 欧美三级少妇高潮 | 麻豆福利在线 | 外国黄色网 | 一本av在线 | 91超碰在线播放 | 天天干视频| 一区二区三区日韩欧美 | 日韩动漫av| 国产一区黄色 | 欧美婷婷精品激情 | av在线资源站 | 欧美激情精品久久久久久免费 | 久久精品一区二区在线观看 | 男女激情视频网站 | 午夜精品一区二区三区在线视频 | 欧美成人精品一区二区 | 欧美综合图片 | 欧美色女人| 欧美一二三视频 | 插插网站| 中文字幕在线视频日韩 | 欧美性受xxxxx | 国产精品视频1区 | 亚洲精品视频在线免费 | 国产91av视频 | 男女插孔视频 | 天天干天天色 | 欧美性猛交 xxxx | 亚洲精品欧美激情 | 毛片av在线播放 | 中国特级毛片 | 久久中文字幕人妻熟av女蜜柚m | 老女人一毛片 | 日本国产在线 | 日本免费一区二区三区四区五六区 | 亚洲av无码一区二区乱子伦as | 国产手机av在线 | 国产伦精品一区二区三区视频黑人 | 情侣在线视频 | 欧美88av | 在线看免费毛片 | 日韩少妇一区二区三区 | 亚洲中文字幕久久无码 | 成片免费观看视频大全 | 亚洲精品国产suv一区 | www夜夜操 | 男人懂的网站 | 日本50路肥熟bbw | 五月激情网站 | 伊人91视频 | 国产黄色片免费观看 | 久久国产三级 | www.中文字幕av | 日日射视频| 国产做爰xxxⅹ性视频国 | 精品一区二区三区四区五区六区 | 亚洲av无码一区东京热久久 | 久久久久久福利 | 亚洲伦理在线播放 | 欧美天天影院 | 久久精品aⅴ无码中文字字幕重口 |