進程間通信(四)—共用記憶體

来源:http://www.cnblogs.com/lenomirei/archive/2016/07/08/5651995.html
-Advertisement-
Play Games

我會用幾篇博客總結一下在Linux中進程之間通信的幾種方法,我會把這個開頭的摘要部分在這個系列的每篇博客中都打出來 進程之間通信的方式 管道 消息隊列 信號 信號量 共用存儲區 套接字(socket) 進程間通信(三)—信號量傳送門:http://www.cnblogs.com/lenomirei/ ...


我會用幾篇博客總結一下在Linux中進程之間通信的幾種方法,我會把這個開頭的摘要部分在這個系列的每篇博客中都打出來

進程之間通信的方式

  • 管道
  • 消息隊列
  • 信號
  • 信號量
  • 共用存儲區
  • 套接字(socket)

進程間通信(三)—信號量傳送門:http://www.cnblogs.com/lenomirei/p/5649792.html

進程間通信(二)—消息隊列傳送門:http://www.cnblogs.com/lenomirei/p/5642575.html

進程間通信(一)—管道傳送門:http://www.cnblogs.com/lenomirei/p/5636339.html

這篇主要記錄的是共用存儲區的相關操作,說是共用存儲區,其實就是共用記憶體,進程擁有的能互相通信存儲區也就有記憶體了吧

為什麼用共用存儲區進行通信?因為快!管道是文件,操作慢,消息隊列創建操作都有消耗所以慢,共用記憶體是要創建好兩個進程都可以直接對這塊記憶體進行操作,互相都是可見的。

為什麼用共用存儲區編寫程式?因為介面簡單!操作絕對比消息隊列簡單好多。

  • 創建共用存儲區

雖然感覺很簡單的事情,但是還是要創建開闢一下,不然每個進程都用自己的地址空間映射到不同的物理地址,哪怕虛擬地址是一樣的,也是各自獨立的,互相不可見,聲明瞭這個共用存儲區之後,才可以往這個公共的區域映射(這樣才有用不是麽)。

  • 函數原型:int shmget(key_t key, size_t size, int shmflg);
  • 頭文件:#include <sys/ipc.h> #include <sys/shm.h>
  • 參數解析
    • key參數通過ftok函數的返回值取得,或者傳入IPC_PRIVATE由操作系統自動分配
    • size表示你要開闢多大的共用存儲空間,PS:分配空間最終會變成分配物理空間,是通過分配整頁的方式實現的,Linux系統下一頁大小是4KB=4096B,小於4096B則分配一頁,size傳入4097則分配兩頁
    • shmflg有IPC_CREAT 和 IPC_EXCL

調用這個函數就可以開闢一個共用存儲區了,可以通過ipcs -m查看當前共用存儲區狀態

第一個鍵值就是傳入的key,shmid標識唯一共用記憶體段,擁有者許可權位元組就不多說了額,這個nattch是指當前有多少個進程連接到該共用存儲區

nattch:只創建共用存儲區是不夠的,你需要把它和進程鏈接,才能讓進程的地址空間中的一段地址映射到共用記憶體段上。

  • 共用存儲區的連接

這就講一下用什麼函數鏈接共用存儲區,需要註意的是,兩個進程都需要鏈接才可以,創建共用存儲區的進程不會自動連接,也需要調用鏈接函數

  • 函數原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 頭文件:#include <sys/types.h> #include <sys.shm.h>
  • 參數解析
    • shmid表示共用存儲區的標識
    • 第二個參數表示共用存儲區的開始地址,如果不是對記憶體十分瞭解建議交給操作系統去做,設置為0
    • shmflg可以設置當前進程的讀寫許可權,SEM_RDONLY之類的,預設0為讀寫均可,測試程式我給了0

每有一個進程調用這個函數,就會使nattch增加1,返回值因為是個空類型的指針常常需要強制轉換

  • 共用存儲區的鏈接的斷開

鏈接使用完之後就斷開是個好習慣,而且對銷毀共用存儲空間也好

  • 函數原型:int shmdt(const void *shmaddr);
  • 頭文件:#include <sys/types.h> #include <sys.shm.h>
  • 參數解析刪除共用存儲區
    • 就是要刪除的共用存儲區的起始地址,因為是空類型的指針,沒必要轉換,直接給來都能刪除

 

 

  • 刪除共用存儲區

最後還是要用到shmctl函數來刪除共用存儲區

  • 函數原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 頭文件:#include <sys/ipc.h> #include <sys/shm.h>
  • 參數解析
    • shmid表示共用存儲區的標識
    • cmd給出IPC_RMID表示刪除
    • 因為第二個參數設置為IPC_RMID表示刪除,第三個參數沒用了,第三個參數直接給NULL(0)

 

事已至此,基本操作就說完了,廢話少說,show me the code

我的程式分為comm.h(公共頭文件)  comm.c(封裝基本函數) server.c(簡易伺服器端) 一共3個文件

功能主要實現了簡單的字元串共用?父進程寫入,子進程列印,就這麼簡單

結果圖並看不出什麼鬼

comm.h

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <string.h>
 4 #include <sys/ipc.h>
 5 #include <unistd.h>
 6 #include <sys/shm.h>
 7 #include <errno.h>
 8 #include <stdlib.h>
 9 
10 
11 #define _PATH_NAME_ "/tmp"
12 #define _PROJ_ID_ 0x6666
13 
14 
15 
16 static int comm_create_ssm(int flags,size_t size);
17 int create_shm(size_t size);
18 int get_shm();
19 char *shm_at(int shm_id);
20 void destory_shm(int shm_id);
21 int shm_dt(char *addr);

 

comm.c

 1 #include "comm.h"
 2 
 3 
 4 static int comm_create_shm(int flags,size_t size)
 5 {
 6   key_t _key=ftok(_PATH_NAME_,_PROJ_ID_);
 7   if(_key<0)
 8   {
 9     printf("%d:%s",errno,strerror(errno));
10   }
11   int shm_id;
12   if((shm_id=shmget(_key,size,flags))<0)
13   {
14     printf("shmget error,%d:%s",errno,strerror(errno));
15   }
16   return shm_id;
17 }
18 
19 
20 int create_shm(size_t size)
21 {
22   int flags=IPC_CREAT |IPC_EXCL;
23   return comm_create_shm(flags,size);
24 }
25 
26 int get_shm()
27 {
28   int flags=IPC_CREAT;
29   return comm_create_shm(flags,0);
30 }
31 
32 char *shm_at(int shm_id)
33 {
34   return (char *)shmat(shm_id,NULL,0);
35 }
36 int shm_dt(char *addr)
37 {
38   return shmdt(addr);
39 }
40 
41 void destory_shm(int shm_id)
42 {
43   shmctl(shm_id,IPC_RMID,0);
44 }

 

server.c

 1 #include "comm.h"
 2 
 3 
 4 
 5 int main()
 6 {
 7   int pid=fork();
 8   if(pid>0)
 9   {
10     //father
11     int shm_id=create_shm(4096);
12     char *buf=shm_at(shm_id);
13     int i=0;
14     while(i<4096)
15     {
16       sleep(1);
17       buf[i]='A';
18       i++;
19       buf[i]='\0';
20     }
21   }
22   else
23   {
24     //child
25     int shm_id=get_shm();
26     char *buf=shm_at(shm_id);
27     while(1)
28     {
29       sleep(1);
30       printf("%s\n",buf);
31     }
32   }
33   return 0;
34 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 【開發過程的隨筆總結,歡迎您的點評,可以做到更加嚴謹】 簡介:mongoDB noSql資料庫 文檔型資料庫 前些天,做一個日誌歸類入庫項目的時候 用mongoDB進行持久化存儲 防止mongoDb的無許可權鏈接,添加了許可權驗證 1 如果mongoDB是開放內網地址的話,不用擔心外部鏈接 2 mong ...
  • 今天在PlateSpin Forge(關於PlateSpin相關介紹,請見最下麵部分簡單介紹) 複製出來的一臺資料庫伺服器上,測試資料庫能否正常啟動時,遇到了“ORA-00600: internal error code, arguments: [kcratr1_lastbwr], [], [], ... ...
  • 基於物品的協同過濾演算法ItemCF 基於item的協同過濾,通過用戶對不同item的評分來評測item之間的相似性,基於item之間的相似性做出推薦。簡單來講就是:給用戶推薦和他之前喜歡的物品相似的物品。 用例說明: 註:基於物品的協同過濾演算法,是目前商用最廣泛的推薦演算法。 剛開始看這個用例,感覺還 ...
  • IDENT_CURRENT('TableName')為當前的最大標識值,IDENT_INCR('TableName')為設置的標識值增量, 兩者相加即為下一個標識值 SELECT IDENT_CURRENT('TableName') + IDENT_INCR('TableName'); 參考鏈接:h ...
  • 介紹 有時候我們需要原封不動的複製一張表的表結構來生成一張新表,MYSQL提供了兩種便捷的方法。 例: CREATE TABLE tb_base( id INT NOT NULL PRIMARY KEY, name VARCHAR(10), KEY ix_name (name)) ENGINE='M ...
  • 協同過濾推薦(Collaborative Filtering Recommendation) 基於用戶的協同過濾分為兩個步驟: 1. 找到與目標用戶興趣相似的用戶集合 2. 找到這個集合中用戶喜歡的、並且目標用戶沒有聽說過的物品推薦給目標用戶 計算兩個用戶的興趣相似度: 設 N(u) 為用戶 u 喜 ...
  • Mongodb 簡單入門(個人學習小記) 1、安裝並註冊成服務:(示例) E:\DevTools\mongodb3.2.6\bin>mongod.exe --bind_ip 127.0.0.1 --logpath "E:\mongodbDataBase\accountValueBase\log\lo ...
  • 1,執行完全備份 這是直接備份到g盤的情況 backup database 資料庫名 to disk='g:\database.bak' 這是備份到備份設備的情況,with init是初始化,也就是直接覆蓋 bakup database 資料庫名 to mybackup with init 2,執行 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...