Linux系統編程-進程間通信(共享內存)

      網友投稿 817 2022-05-29

      Linux系統編程-進程間通信(共享內存)

      前面陸續介紹了標準管道流、無名管道、命名管道、mmap內存映射,這篇文章介紹共享內存段。

      1. 共享內存機制(shmget)

      共享內存也是進程間(進程間不需要有繼承關系)通信的一種常用手段。一般OS通過內存映射與頁交換技術,使進程的內存空間映射到不同的物理內存,這樣能保證每個進程運行的獨立性,不至于受其它進程的影響。但可以通過共享內存的方式,使不同進程的虛擬內存映射到同一塊物理內存,一個進程往這塊物理內存中更新的數據,另外的進程可以立即看到這塊物理內存中修改的內容。

      內存映射和共享內存的區別:

      mmap內存映射:跟普通文件的讀寫相比,加快對文件/設備的訪問速度。

      shmget共享內存:多進程間進行通信。

      原理及實現:

      system V IPC機制下的共享內存本質是一段特殊的內存區域,進程間需要共享的數據被放在該共享內存區域中,所有需要訪問該共享區域的進程都要把該共享區域映射到本進程的地址空間中去。這樣一個使用共享內存的進程可以將信息寫入該空間,而另一個使用共享內存的進程又可以通過簡單的內存讀操作獲取剛才寫入的信息,使得兩個不同進程之間進行了一次信息交換,從而實現進程間的通信。共享內存允許一個或多個進程通過同時出現在它們的虛擬地址空間的內存進行通信,而這塊虛擬內存的頁面被每個共享進程的頁表條目所引用,同時并不需要在所有進程的虛擬內存都有相同的地址。進程對象對于共享內存的訪問通過key(鍵)來控制,同時通過key進行訪問權限的檢查。

      2. 共享內存機制相關函數接口介紹

      2.1 ftok函數

      #include #include key_t ftok(const char *pathname, int proj_id);

      函數功能: 用于創建一個關鍵字,可以用該關鍵字關聯一個共享內存段。

      參數介紹:

      (1) pathname:全路徑文件名,并且該文件必須可訪問。

      (2) proj_id:通常傳入一非0字符。通過pathname和proj_id組合可以創建唯一的key(對任何進程都是唯一且相同的)。

      返回值:

      如果調用成功,返回一關鍵字,否則返回-1。

      2.2 shmge函數

      #include #include int shmget(key_t key, size_t size, int shmflg);

      shmget 函數用于創建或打開一共享內存段,該內存段由函數的第一個參數標識。函數成功則返回一個該共享內存段的唯一標識號(唯一的標識了這個共享內存段),對任何進程都是唯一且相同的。

      參數介紹

      (1) key是一個與共享內存段相關聯的關鍵字,如果事先已經存在一個與指定關鍵字關聯的共享內存段,則直接返回該內存段的標識。key的值既可以用ftok函數產生,也可以是IPC_RPIVATE(用于創建一個只屬于創建進程的共享內存,主要用于父子通信),表示總是創建新的共享內存段。

      (2) size指定共享內存段的大小,以字節為單位。

      (3) shmflg是一掩碼合成值,可以是訪問權限值與(IPC_CREAT或IPC_EXCL)的合成。IPC_CREAT表示如果不存在該內存段,則創建它。IPC_EXCL表示如果該內存段存在,則函數返回失敗結果(-1)。

      返回值

      如果調用成功,返回內存段標識,否則返回-1。

      2.3 shmat函數

      函數shmat將共享內存段映射到進程空間的某一地址。

      #include #include void *shmat(int shmid, const void *shmaddr, int shmflg);

      注意: 只有管理員用戶權限才可以獲取內存地址

      參數

      (1) shmid 是共享內存段的標識通常應該是shmget的成功返回值。

      (2) shmaddr指定的是共享內存連接到當前進程中的地址位置。通常是NULL,表示讓系統來選擇共享內存出現的地址。

      (3) shmflg是一組位標識,通常為0即可。如果是SHM_RDONLY的話,就是只讀模式。其它的是讀寫模式。

      返回值

      如果調用成功,返回映射后的進程空間的首地址,否則返回(void*)-1。

      2.4 shmdt函數

      shmdt用于將共享內存段與進程空間分離,與shmat函數相反。用于關閉共享內存段。

      #include #include int shmdt(const void *shmaddr);

      參數

      shmaddr通常為shmat的成功返回值。

      返回值

      成功返回0,失敗時返回-1。

      注意:只是將共享內存分離,并沒有沒刪除它,只是使得該共享內存對當前進程不再可用。

      2.5 shmctl函數

      函數shmctl是共享內存的控制函數,可以用來刪除共享內存段。

      #include #include int shmctl(int shmid, int cmd, struct shmid_ds *buf);

      參數:

      (1)shmid:共享內存段標識 通常應該是shmget的成功返回值

      (2)cmd:對共享內存段的操作方式

      可選為IPC_STAT,IPC_SET,IPC_RMID。通常為IPC_RMID,表示刪除共享內存段。

      (3)buf:表示共享內存段的信息結構體數據,通常為NULL。

      例如: shmctl(kshareMem,IPC_RMID,NULL)表示刪除共享內存段kHareMem

      3. 案例: 基本用法示例1

      3.1 創建內存段寫數據示例

      下面代碼使用/work/1.dat的文件屬性獲取key,作為內存標識符;再創建共享內存段,映射內存地址,然后向內存空間寫入數據"hello world",再取消映射。這時候其他進程就可以訪問這個內存段讀取里面的數據。

      #include #include #include #include #include #include int main() { key_t key = ftok("/work/1.dat",1); //1. 寫入端先用ftok函數獲得key int shmid = shmget(key,4096,IPC_CREAT); //2. 寫入端用shmget函數創建共享內存段 printf("key = %d shmid = %d\n", key, shmid); char *p = (char *)shmat(shmid, NULL, 0); //3. 獲得共享內存段的首地址 memset(p, 0, 4096); // 清除內存空間 memcpy(p, "hello world", 4096); //4. 往共享內存段中寫入內容 shmdt(p); //5. 關閉共享內存段 return 0; }

      3.2 打開內存段讀取示例

      下面代碼用來訪問,上面寫端代碼創建的共享內存段里的數據,流程一樣。shmget函數如果判斷出共享內存段已經存在,就不會再重復創建(依靠key作為標識符判斷的);接著再映射空間地址,讀取內存里的數據,打印出hello world,最后再銷毀內存空間。

      #include #include #include #include #include int main() { key_t key = ftok("/work/1.dat",1); int shmid = shmget(key,4096,IPC_CREAT); printf("key = %d shmid = %d\n", key, shmid); char *p = (char *)shmat(shmid, NULL, 0); printf("receive the data:%s\n",p); //4. 讀取共享內存段中的內容 shmctl(shmid, IPC_RMID, 0); //5. 刪除共享內存段 //不刪除內存空間,數據會一直存在的 return 0; }

      4. 案例: 基本用法示例2

      上面例子代碼是通過獲取文件的屬性得到唯一的key,實際上也可以自己指定key,只要保證唯一性即可。

      4.1 創建內存寫數據示例

      #include #include #include #include #include #include #include #include #include #include #include int main(int argc,char **argv) { /*1. 創建共享內存段*/ int shmid=shmget(123456,4096,IPC_CREAT); /*2. 映射共享內存到進程空間*/ unsigned char *p; p=shmat(shmid,NULL,0); /*3. 對共享內存實現讀寫*/ strcpy(p,"linux下進程間通信共享內存學習"); /*4. 取消映射*/ shmdt(p); return 0; }

      4.2 打開內存讀數據示例

      #include #include #include #include #include #include #include #include #include #include #include int main(int argc,char **argv) { /*1. 創建共享內存段*/ int shmid=shmget(123456,4096,IPC_CREAT); /*2. 映射共享內存到進程空間*/ unsigned char *p; p=shmat(shmid,NULL,0); /*3. 對共享內存實現讀寫*/ printf("p=%s\n",p); /*4. 取消映射*/ shmdt(p); /*5. 釋放共享內存空間*/ shmctl(shmid,IPC_RMID,NULL); return 0; }

      Linux 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:(更新時間)2021年06月14日 網絡安全 文件共享服務器
      下一篇:【Smashing專欄】選擇移動界面原型設計工具的12個因素
      相關文章
      亚洲va久久久噜噜噜久久天堂| 亚洲欧美国产欧美色欲| 精品亚洲国产成人av| 亚洲天堂2016| 亚洲福利视频网址| 亚洲黄色三级视频| 91久久亚洲国产成人精品性色| 国产亚洲美女精品久久久久狼| 国产成人精品日本亚洲专区61| 国产成人人综合亚洲欧美丁香花| 亚洲乱色熟女一区二区三区蜜臀| 亚洲午夜无码毛片av久久京东热| 亚洲小说图区综合在线| 亚洲成a人片在线观看天堂无码 | 亚洲色最新高清av网站| 亚洲久悠悠色悠在线播放| 日本亚洲免费无线码| 亚洲人成色777777老人头| 亚洲狠狠色丁香婷婷综合| 国产成人综合亚洲| 亚洲国产专区一区| 亚洲综合最新无码专区| 久久亚洲中文字幕精品一区| 亚洲精品无码av人在线观看| 亚洲AV无码一区二区乱孑伦AS| 亚洲精品自产拍在线观看动漫| 亚洲五月六月丁香激情| 亚洲精品人成电影网| 亚洲一区在线视频| 亚洲精品无码久久久久YW| 亚洲 小说区 图片区 都市| 久久久久久亚洲精品不卡| 精品亚洲一区二区| 亚洲综合久久综合激情久久| 91亚洲国产成人久久精品| 四虎亚洲精品高清在线观看| 亚洲AV色欲色欲WWW| 亚洲国产av无码精品| 国产亚洲真人做受在线观看| 亚洲天堂久久精品| 亚洲综合一区国产精品|