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

歡迎訪問 生活随笔!

生活随笔

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

linux

linux信号量配合共享内存应用分析(详解)

發布時間:2023/12/31 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux信号量配合共享内存应用分析(详解) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

共享內存與信號量

共享內存,指的是兩個不相關的進程訪問同一個邏輯內存,進程可以將同一段物理內存連接到他們自己的地址空間中,所有的進程都可以訪問共享內存中的地址。如果某個進程向共享內存寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的任何其他進程。如果我們不允許兩個進程同時對共享內存進行讀寫操作,光靠共享內存的機制是做不到的。共享內存并未提供同步機制,也就是說,在第一個進程結束對共享內存的寫操作之前,并無自動機制可以阻止第二個進程開始對它進行讀取,所以我們通常需要用其他的機制來同步對共享內存的訪問,例如信號量。

共享內存的操作函數說明

1、創建共享內存(創建或者打開一塊內存后,會返回該內存的索引,進程通過該索引可以對共享內存進行連接)(記錄一個知識點:fortk第一個參數是輸入一個路徑,如果路勁不存在會返回一個默認值)

int shmget(key_t key, size_t size, int shmflg)創建共享內存/* key:由ftok生成的key標識,標識系統的唯一IPC資源。size:需要申請共享內存的大小。在操作系統中,申請內存的最小單位為頁,一頁是4k字節,為了避免內存碎片,我們一般申請的內存大小為頁的整數倍。shmflg:如果要創建新的共享內存,需要使用IPC_CREAT,IPC_EXCL,如果是已經存在的,可以使用IPC_CREAT或直接傳0。*/

2、連接共享內存(不同的進程通過此函數,掛載到同一片內存上)

void *shmat(int shmid, const void *shmaddr, int shmflg);/*shmid:共享存儲段的標識符。shmaddr:shmaddr = 0,則存儲段連接到由內核選擇的第一個可以地址上(推薦使用)。shmflg:若指定了SHM_RDONLY位,則以只讀方式連接此段,否則以讀寫方式連接此段。返回值:成功返回共享存儲段的指針(虛擬地址),并且內核將使其與該共享存儲段相關的shmid_ds結構中的shm_nattch計數器加1(類似于引用計數);出錯返回-1。*/

3、解除共享內存的連接(當一個進程不需要共享內存的時候,就需要解除與該共享內存的連接。該函數并不刪除所指定的共享內存區,而是將之前用shmat函數連接好的共享內存區脫離目前的進程。)

int shmdt(const void *shmaddr)/* shmaddr:連接以后返回的地址。返回值:成功返回0,并將shmid_ds結構體中的 shm_nattch計數器減1;出錯返回-1。*/

4、銷毀共享內存

int shmctl(int shmid, int cmd, struct shmid_ds *buf); /* shmid:共享存儲段標識符。參數cmd:指定的執行操作,設置為IPC_RMID時表示可以刪除共享內存。參數buf:設置為NULL即可。返回值:成功返回0,失敗返回-1。 */

信號量的操作函數說明

說信號量之前,先提一句,信號量和信號是完全兩個不同的東西,關于信號可以去看我這篇博客 ,點擊進入

信號量就是用來解決進程間的同步與互斥問題的一種進程間通信機制。值得一提的是,二值信號量與自旋鎖的效果差不多,但有一點需要注意是,信號量會引起進程的睡眠屬于睡眠鎖,不要在中斷中用信號量,不要在持鎖時,進行進程的切換!

1、信號量的建立(會返回一個信號標識符,用來指向這個信號量結構)

int semget(key_t key, int nsems, int semflg)/*key : 定義一個唯一的標識符nsems: 需要創建的信號量數量semflg : IPC_CREAT(一般用這個):當semflg&IPC_CREAT為真時,如果內核中不存在鍵值與key相等的信號量集,則新建一個信號量集;如果存在這樣的信號量集,返回此信號量集的標識符 。IPC_CREAT|IPC_EXCL:如果內核中不存在鍵值與key相等的信號量集,則新建一個消息隊列;如果存在這樣的信號量集則報錯*/

2、對信號量進行設置

int semctl(int semid, int semnum, int cmd, union semun arg)/*semid: 就是由semget()得到的semnum: 當用到信號量集的時候才用,默認為0就好了cmd:你就用SETVAL這個好了,用來把信號量初始化為一個已知的值。其他的我也沒用過哈哈...arg: union semun {short val; /*就把這個val值設置一下就好了,其他的不用管,默認就好*/struct semid_ds* buf; /*IPC_STAT、IPC_SET用的semid_ds結構*/unsigned short* array; /*SETALL、GETALL用的數組值*/struct seminfo *buf; /*為控制IPC_INFO提供的緩存*/} arg;*/

3、信號量的P操作或V操作(可以簡單的理解為,信號量的獲取與釋放,主要看各個val值,如果你把val設置為1 ,也就是資源只支持一個進程訪問,該進程訪問時進程P操作,會把val減1,當另一進程請求訪問時,發現val已經等于0了,就會被堵塞)

int semop(int semid, struct sembuf *sops, unsigned nsops)/*semid:信號量集標識符struct sembuf * sops : struct sembuf {short semnum; /*信號量集合中的信號量編號,0代表第1個信號量*/short val;/*若val>0進行V操作信號量值加val,表示進程釋放控制的資源 *//*若val<0進行P操作信號量值減val,則調用進程阻塞,直到資源可用;若設置IPC_NOWAIT不會睡眠,進 程直接返回EAGAIN錯誤*//*若val==0時阻塞等待信號量為0,調用進程進入睡眠狀態,直到信號值為0;若設置IPC_NOWAIT,進程不會 睡眠,直接返回EAGAIN錯誤*/short flag; /*0 設置信號量的默認操作*//*IPC_NOWAIT設置信號量操作不等待*/ /*SEM_UNDO 選項會讓內核記錄一個與調用進程相關的UNDO記錄,如果該進程崩潰,則根據這個進程的UNDO記錄自動恢復相應信號量的計數值*//*nsops:進行操作信號量的個數,即sops結構變量的個數,需大于或等于1。最常見設置此值等于1,只完成對一個信號量的操作*/*/

信號量配合共享內存應用

comm.h文件

//comm.h #ifndef _COMM_H__ #define _COMM_H__#include<stdio.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<sys/sem.h>#define PATHNAME "." #define PROJ_ID 0x6666 #define PROJ_mm 0x6667int CreateShm(int size); int DestroyShm(int shmid); int GetShm(int size);int init_sem(int semid, int num, int val);int sem_p(int semid, int num) ;int sem_p(int semid, int num) ;int sem_v(int semid, int num) ;#endif

comm.c

//comm.c/*void *shmat(int shmid, const void *shmaddr, int shmflg);參數shmid:共享存儲段的標識符。參數*shmaddr:shmaddr = 0,則存儲段連接到由內核選擇的第一個可以地址上(推薦使用)。參數shmflg:若指定了SHM_RDONLY位,則以只讀方式連接此段,否則以讀寫方式連接此段。返回值:成功返回共享存儲段的指針(虛擬地址),并且內核將使其與該共享存儲段相關的shmid_ds結構中的shm_nattch計數器加1(類似于引用計數);出錯返回-1。*/ #include"comm.h"//以下定義的是共享內存的函數 static int CommShm(int size,int flags) {key_t key = ftok(PATHNAME,PROJ_ID); //由ftok生成的key標識,標識系統的唯一IPC資源。“PATHNAME”就是引用一個絕對路勁if(key < 0){perror("ftok");return -1;}int shmid = 0;/*int shmget(key_t key, size_t size, int shmflg)創建共享內存參數key:由ftok生成的key標識,標識系統的唯一IPC資源。參數size:需要申請共享內存的大小。在操作系統中,申請內存的最小單位為頁,一頁是4k字節,為了避免內存碎片,我們一般申請的內存大小為頁的整數倍。參數shmflg:如果要創建新的共享內存,需要使用IPC_CREAT,IPC_EXCL,如果是已經存在的,可以使用IPC_CREAT或直接傳0。*/if((shmid = shmget(key,size,flags)) < 0){perror("shmget");return -2;}return shmid; } int DestroyShm(int shmid) {if(shmctl(shmid,IPC_RMID,NULL) < 0){perror("shmctl");return -1;}return 0; } int CreateShm(int size) {return CommShm(size,IPC_CREAT | IPC_EXCL | 0666); } int GetShm(int size) {return CommShm(size,IPC_CREAT); }//以下定義的是信號量的函數union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */ };int init_sem(int semid, int num, int val)// num = 0 val = 1 {union semun myun;myun.val = val;if(semctl(semid, num, SETVAL, myun) < 0) /*用來直接控制信號量信息:對信號量進行刪除或者控制// 0代表對1個信號來量初始化,即有1個資源 SETVAL:用來把信號量初始化為一個已知的值。p 這個值通過union semun中的val成員設置,其作用是在信號量第一次使用前對它進行設置。IPC_RMID:用于刪除一個已經無需繼續使用的信號量標識符。*/{perror("semctl");exit(1);}return 0; }int sem_p(int semid, int num) {struct sembuf mybuf;// 對信號量做減1操作,即等待P(sv)mybuf.sem_num = num;mybuf.sem_op = -1;mybuf.sem_flg = SEM_UNDO;if(semop(semid, &mybuf, 1) < 0){perror("semop");exit(1);}return 0; }int sem_v(int semid, int num) {struct sembuf mybuf; 這是一個釋放操作,它使信號量變為可用,即發送信號V(sv)mybuf.sem_num = num;mybuf.sem_op = 1;mybuf.sem_flg = SEM_UNDO;if(semop(semid, &mybuf, 1) < 0){perror("semop");exit(1);}return 0; }

client.c

//client.c #include"comm.h"int main() {int semid ;key_t sem_key;if((sem_key = ftok(PATHNAME,PROJ_mm)) < 0){perror("ftok failed .\n");exit(-1);}semid = semget(sem_key, 0, IPC_CREAT); //創建一個新信號量或取得一個已有信號量,權限為666int shmid = GetShm(4096);sleep(1);char *addr = shmat(shmid,NULL,0);sleep(2);int i = 0;sem_p(semid,0);//獲取信號量while(i < 26){addr[i] = 'A' + i;i++;addr[i] = 0;sleep(1);}sem_v(semid,0);//釋放信號量shmdt(addr);semctl (semid, 1, IPC_RMID, NULL);DestroyShm(shmid);sleep(2);return 0; }

server.c

//server.c #include"comm.h"int main() {int semid ;key_t sem_key;if((sem_key = ftok(PATHNAME,PROJ_mm)) < 0){perror("ftok failed .\n");exit(-1);}semid = semget(sem_key,1,IPC_CREAT|IPC_EXCL|0666); //創建一個新信號量或取得一個已有信號量,權限為666init_sem (semid, 0, 1); //初始化這個信號量int shmid = CreateShm(4096);sleep(1);char *addr = shmat(shmid,NULL,0);sleep(2);int i = 0;getchar(); //暫停在這,讓客服端先拿到信號量,當client運行后,按下回車鍵,讓server程序繼續運行sem_p(semid,0);//獲取信號量while(i++ < 26){printf("client# %s\n",addr);sleep(1);}sem_v(semid,0);//釋放信號量shmdt(addr);sleep(2);return 0; }

Makefile

all:server clientclient:client.c comm.cgcc -o $@ $^ server:server.c comm.cgcc -o $@ $^ clean:rm -f client server

不加信號量的實驗結果如下

加上信號量的實驗結果如下

總結 ,從這個兩個結果可以看出,不加信號量的時候,讀取數據和寫入數據是宏觀是同時進行的,會存在讀取到的數據不完整的現象,而加上信號量后,讀取數據進程,會等待數據全部寫完后,在進行讀取。保證了讀到的數據的完整性和讀寫進程的同步性

總結

以上是生活随笔為你收集整理的linux信号量配合共享内存应用分析(详解)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: www精品| a人片| 插久久| 五月天av影院 | 久草www | 12av在线| 97人人射| 91麻豆精品秘密入口 | 在线一二区 | 偷拍夫妻性生活 | 日本理论片午伦夜理片在线观看 | 国产电影一区在线观看 | 日日拍拍 | 青青草91久久久久久久久 | 伊人网大| 免费看国产片在线观看 | www色| 亚洲嫩草影院 | 在线无 | 国语对白真实视频播放 | 美女被草网站 | 日韩aaa | 国产精品分类 | 男人疯狂高潮呻吟视频 | 国产视频三级 | 99一级片 | 欧美黑吊大战白妞 | av中出| 亚洲高清精品视频 | 国产精品精品久久久 | 国产91热爆ts人妖系列 | 欧美爱爱爱| av有码在线观看 | 欧美性潮喷xxxxx免费视频看 | 精品午夜久久久 | 一卡二卡三卡在线视频 | 国产chinese中国hdxxxx | 五月激情五月婷婷 | 九九精品视频在线观看 | 鲁大师私人影院在线观看 | 免费在线你懂的 | 寡妇av| 91麻豆精品视频 | 国产一线二线三线女 | 久久久999视频 | 国产传媒视频 | 精品黑人一区二区三区在线观看 | 国产ts丝袜人妖系列视频 | 天天看天天干 | 久在线播放| 99热偷拍| 色成人综合网 | 五月天在线播放 | 99久久久无码国产精品免费麻豆 | 变态视屏| 免费观看黄色一级视频 | 97麻豆| 亚洲经典一区 | 精品国产无码AV | 爱爱爱免费视频 | 日韩一区二区在线播放 | 香蕉视频免费在线播放 | 日本一区二区三区视频免费看 | 丰满人妻一区二区三区在线 | 国产aⅴ激情无码久久久无码 | 波多野结衣一区二区三区 | 91精品国产高清一区二区三蜜臀 | 亚洲熟女乱色综合亚洲小说 | 中文字幕精 | 荫蒂被男人添免费视频 | 久久久久免费精品视频 | www.黄色大片 | 欧美黑人又粗又大的性格特点 | 天堂bt在线| 波多野结衣一区二区三区在线观看 | 午夜影院在线视频 | 中文在线字幕免费观 | 久久亚洲国产精品 | 国产二区自拍 | 在线观看亚洲一区 | 青青草五月天 | 97视频人人| 日韩欧美色图 | 国产午夜精品理论片在线 | 日韩欧美在线一区二区 | 36d大奶| 国产精品精品国产色婷婷 | av女人的天堂 | 成人欧美在线视频 | 成年人视频在线看 | 免费亚洲精品 | 青青青草视频在线 | 少妇粉嫩小泬白浆流出 | 潘金莲性xxxxhd | 波多野结衣在线播放视频 | 国产欧美日韩精品一区二区三区 | 一本久久久久 | sese久久 | 免费观看黄色一级视频 |