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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux c 基于内存的进程通信—共享内存、共享队列(消息队列)

發布時間:2025/5/22 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux c 基于内存的进程通信—共享内存、共享队列(消息队列) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基于內存的進程通信:

1.??????內核共享內存

編程模型:

?? ?1.1.創建共享內存,得到一個ID? shmget

1.2.把ID影射成虛擬地址(掛載)? shmat

?????? 1.3.使用虛擬地址訪問內核共享內存使用任何內存函數與運算符號??????????????????????? 1.4.卸載虛擬地址 shmdt

?????? 1.5.刪除共享內存 shctl(修改/獲取共享內存的屬性)

?

案例:

A.創建共享內存,并且修改內存數據

1.??????創建共享內存

??????????????????????????????#include<sys/shm.h>

??????????????????????????????intshmget(key_t key,//為什么需要key

????????????????????????????????????????????????????????????????????? ?int size,//共享內存大小

????????????????????????????????????????????????????????????????????? ?int flags//共享內存的屬性與權限

???????????????????????????????????????????????? )

????????????????????????????????????????? 為什么要key_t:

??????????????????????????????????????????????????????? 約定創建與訪問的是同一個共享內存。Key為兩個進程之間訪問同一塊共享內存的約定

注:key需要唯一性,因為我們不能保證我們自己定義的key的唯一性,所以為了保證kay的唯一性,我們需要用某個文件對應的整數來充當kay值,可以用ftok函數來將一個文件轉化為一個kay值。(一般我們用兩個進程的共同的工程目錄文件來確定kay值)

?

???????????????????????? ftok函數:

??????????????????????????????????#include<sys/ipc.h>

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

???????????????????????? ??????????參數二:一個控制因子。建議在0—255之間

????????????????????????????????????????? 第三個參數:

?????????????????????????????????????????????????????????????? 方式|權限

?????????????????????????????????????????????????????????????? 方式:創建 IPC_CREAT? IPC_EXCL(如果內存已經創建,直接錯誤返回)

?????????????????????????????????????????????????????????????? 打開:0

??????????????????????????????????????????????????????? 常見的兩種方式:

????????????????????????????????????????????????????????????????????? 創建:IPC_CREAT|IPC_EXCL | 0666;

????????????????????????????????????????????????????????????????????? 打開:0

????????????????????????????????????????????????????????????????????????????

?????????????????????????????????? 返回:

???????????????????????????????????????????????? 成功返回共享內存ID

???????????????????????????????????????????????? 失敗返回-1?????????????????

?????? ???????????????????? 失敗返回-1?????????????????

???????????????????? B.根據ID得到共享內存,并且訪問內存數據。

?

?????????????????????????????????? 掛載共享內存

void* shmat(int id,

???????????????????????????????????????????????? void*startaddr,//0:系統指定首地址

???????????????????????????????????????????????? intflags)//掛載方式,建議0默認讀寫,可以使用IPC_RDONLY

???????????????????????????? 返回值:合法地址成功,-1失敗

???????????????????? C.刪除

?????????????????????????????????? intshmctl(int id,//被操作的共享內存ID

???????????????????????????????????????????????? inthow,//操作方式:一共三種操作

???????????????????????????????????????????????? structshmid_ds*ds)//共享內存屬性

?????????????????????????????????? how:

???????????????????????????????????????????????? IPC_STAT???

???????????????????????????????????????????????? IPC_SET???? //修改屬性

???????????????????????????????????????????????? IPC_RMID?? //刪除?? 參數三無用

?

?

案例代碼:

ShmA.c

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<sys/shm.h>

#include<sys/ipc.h>

?

void???main()

{

??????key_t?? key;

??????int???? shmid;

??????int * p;

??????//1.創建共享內存

??????key=ftok( “.” , 255 );?? //用當前路徑的目錄來確定kay值

??????if(key == -1)? printf(“ftok error%m\n”) ,? exit( - 1 );

??????shmid=shmget( key , 4 , IPC_CREAT|IPC_EXCL | 0666 );

??????if(shmid == -1) printf(“shmget error %m\n”) , exit( -1 );

??????//2.掛載共享內存

??????p=shmat( shmid , 0 , 0);

??????if(p==(int *) - 1) printf(“at error %m\n”) , exit( -1 );

??????//3.訪問共享內存

??????*p=999;

??????//4.卸載共享內存

??????shmdt(shmid);

??????//刪除共享內存

??????shctl( shmid , IPC_RMID , 0);

}

不創建共享內存,只訪問已有的

shmB.c

?

ShmA.c

#include<stdio.h>

#include<stdlib.h>

#include<signal.h>

#include<sys/shm.h>

#include<sys/ipc.h>

?

void???main()

{

??????key_t?? key;

??????int???? shmid;

??????int * p;

??????//1.得到共享內存

??????key=ftok( “.” , 255 );?? //用當前路徑的目錄來確定kay值

??????if(key == -1)? printf(“ftok error%m\n”) ,? exit( - 1 );

??????shmid=shmget( key , 4 ,0 );

??????if(shmid == -1) printf(“shmget error %m\n”) , exit( -1 );

??????//2.掛載共享內存

???? ??p=shmat( shmid , 0 , 0);

??????if(p==(int *) - 1) printf(“at error %m\n”) , exit( -1 );

??????//3.訪問共享內存

??????printf(“%d\n”,*p);

??????//4.卸載共享內存

??????shmdt(shmid);

????

}

?

?

2.??????內核共享隊列(有序)

??? ????????編程模型:

????????????????????????????????????????? 2.1.創建共享隊列/得到隊列msgget

????????????????????????????????????????? 2.2.使用隊列(發送消息msgsnd/接收消息msgrcv)

????????????????????????????????????????? 2.3.刪除隊列msgctl

?

案例:

???????????????????? 創建共享隊列

???????????#include<sys/msg.h>

?????????????????????????????????? intmsgget(key_t,int); 除了不用指定大小,和shmget函數的參數一樣?????????????????????????????

???????????????????? 發送消息

?????????????????????????????????? intmsgsnd(

???????????????????????????????????????????????? intid,//消息隊列ID

???????????????????????????????????????????????? constvoid *msg,//要發送消息

???????????????????????????????????????????????? size_tlen,//消息的長度

???????????????????? ??????????????????????????? int flags//發送消息的方式,建議為0

????????????????????????????????????????? );

?????????????????????????????????? 返回:

???????????????????????????????????????????????? -1:失敗

???????????????????????????????????????????????? ?0:成功??

?????????????????????????????????? 第二個參數的消息有固定的格式

??????????????????????????????????????????????????????? 4字節:表示消息的類型

??????????????????????????????????????????????????????? 若干字節:消息內容。

??????????????????? ?消息格式:(該結構體需要我們自己定義)

????????????????????????????? struct? msgbuf{

?????????????????????????????????? long?? mtype;?//消息類型

?????????????????????????????????? char?? mtext[1]; //消息內容

????????????????????????????? }

?????????????????????????????????? 第三個參數:

??????????????????????????????????????????????????????? 消息的大小,不包含類型的4個字節

????????????? 接收消息:

?????????????????????? size_t?? msgrcv(int id ,

void * msgp ,

size_t msgsz, ,

long msgtype , //那種類型的消息

int? msgflg);

????????????????????? 返回:

?????????????????????????? -1:失敗

?????????????????????????? 大小:成功

?????????????? 刪除隊列:msgctl 參數和shctl一樣

?

案例代碼:

?

#include<unistd.h>

#include<sys/ipc.h>

#include<sys/msg.h>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

?

struct??msgbuf

{

?????long? type;

?????char? data[32];

}

?

void?main()

{

????key_t? key;

????int msgid;

????//1創建消息隊列

???? key= ftok(“ . ” , 254);

????if(key == -1) printf(“ftok error:%m\n”) , exit(-1);

????msgid= msgget(key,IPC_CREAT | IPC_EXCL|0666);

???? if(msgid==-1) printf(“get error : %m\n”), exit(-1);

????//2構造消息

???? struct? msgbuf msg;

????//3發送消息

???? for(i=1;i<=10;i++)

????{

??????????msg.type=1;??????? //消息類型自己定義一個long類型

??????????sprintf(msg.data? , “Message:%d”,i);

??????????msgsnd(msgid ,&msg , strlen(msg.data) , 0);

????}

????//4刪除隊列

???? //msgctl(msgid, IPC_RMID,0);

}

?

?

#include<unistd.h>

#include<sys/ipc.h>

#include<sys/msg.h>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

?

struct??msgbuf

{

?????long? type;

?????char? data[32];

}

?

void?main()

{

????key_t? key;

????int msgid;

????//1得到消息隊列

????key = ftok(“ . ” , 254);

????if(key == -1) printf(“ftok error:%m\n”) , exit(-1);

????msgid= msgget(key,0);

????if(msgid== -1) printf(“get error : %m\n”), exit(-1);

????//2構造消息

???? struct? msgbuf msg;

????//3接收消息

???? while(1)

????{

?????????bzero(&msg,sizeof(msg));

?????????msgrcv(msgid , & msg sizeof(msg.data) , 1 , 0);

?????????printf(“%s\n”,msg.data);

????}

}

?

說明:如果消息隊列中沒有消息了讀取消息的程序會阻塞等待

當程序發送消息到隊列中,一個程序讀取了所以消息,隊列中就沒有消息,就無法再讀取了,只能等待在發送消息后在讀取消息。

?

?

?

轉載于:https://www.cnblogs.com/bbsno1/p/3260627.html

總結

以上是生活随笔為你收集整理的Linux c 基于内存的进程通信—共享内存、共享队列(消息队列)的全部內容,希望文章能夠幫你解決所遇到的問題。

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