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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IPC 共享内存和 消息队列(发送、接收、移除)以及键值的生成

發(fā)布時間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IPC 共享内存和 消息队列(发送、接收、移除)以及键值的生成 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、消息對列
消息隊列,是消息的鏈接表,存放在內(nèi)核中。一個消息隊列由一個標識符(即隊列ID)來標識。
特點:

消息隊列是面向記錄的,其中的消息具有特定的格式以及特定的優(yōu)先級。消息隊列獨立于發(fā)送與接收進程。進程終止時,消息隊列及其內(nèi)容并不會被刪除。消息隊列可以實現(xiàn)消息的隨機查詢,消息不一定要以先進先出的次序讀取,也可以按消息的類型讀取。

原型:

#include <sys/msg.h>// 創(chuàng)建或打開消息隊列:成功返回隊列ID,失敗返回-1,flag是打開隊列的方式。int msgget(key_t key, int flag);// 添加消息:成功返回0,失敗返回-1,ptr是消息,size是消息的大小,flag是標志位。int msgsnd(int msqid, const void *ptr, size_t size, int flag);// 讀取消息:成功返回消息數(shù)據(jù)的長度,失敗返回-1,ptr是消息,size是消息的大小,type是消息的類型,flag是標志位。int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);// 控制消息隊列:成功返回0,失敗返回-1int msgctl(int msqid, int cmd, struct msqid_ds *buf);

在以下兩種情況下,msgget將創(chuàng)建一個新的消息隊列:

如果沒有與鍵值key相對應的消息隊列,并且flag中包含了IPC_CREAT標志位。 key參數(shù)為IPC_PRIVATE。

函數(shù)msgrcv在讀取消息隊列時,type參數(shù)有下面幾種情況:

type == 0,返回隊列中的第一個消息; type > 0,返回隊列中消息類型為 type 的第一個消息; type < 0,返回隊列中消息類型值小于或等于 type 絕對值的消息,如果有多個,則取類型值最小的消息。

可以看出,type值非 0 時用于以非先進先出次序讀消息。也可以把 type 看做優(yōu)先級的權(quán)值。(其他的參數(shù)解釋,請自行Google之)

ftok函數(shù)
系統(tǒng)建立IPC通訊 (消息隊列、信號量和共享內(nèi)存) 時必須指定一個ID值。通常情況下,該id值通過ftok函數(shù)得到。

#include <sys/types.h> #include <sys/ipc.h> key_t ftok( const char * fname, int id )

fname就是你指定的文件名(已經(jīng)存在的文件名),一般使用當前目錄,如:
key_t key;
key = ftok(".", 1); 這樣就是將fname設為當前目錄。
id是子序號。雖然是int類型,但是只使用8bits(1-255)。
在一般的UNIX實現(xiàn)中,是將文件的索引節(jié)點號取出,前面加上子序號得到key_t的返回值。
如指定文件的索引節(jié)點號為65538,換算成16進制為0x010002,而你指定的ID值為38,換算成16進制為0x26,則最后的key_t返回值為0x26010002。
查詢文件索引節(jié)點號的方法是: ls -i
當刪除重建文件后,索引節(jié)點號由操作系統(tǒng)根據(jù)當時文件系統(tǒng)的使用情況分配,因此與原來不同,所以得到的索引節(jié)點號也不同。

接收代碼演示

#include<stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include<string.h> struct msgbuf {long mtype; //信息的類型,必須大于0char mtext[128];//信息數(shù)據(jù)存放 }; int main() {//1.huoqu duiliekey_t key;key=ftok(".",'z');struct msgbuf readbuf;printf("key =%x\n",key);//%x 是六進制的形式struct msgbuf sendbuf={988,"thank you for reach"};int msgid=msgget(key,IPC_CREAT|0777);//IPC_CREAT|0777分別表示創(chuàng)建隊列,和隊列的權(quán)限 // printf("ID=%x",msgid);if(msgid==-1){printf("creat fail\n");}msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),888,0);// 如果最后一個為0,以默認的方式來讀,讀不到的話會堵塞msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);printf("read from que:%s\n",readbuf.mtext);msgctl(msgid,IPC_RMID,NULL);return 0; }

發(fā)送代碼演示

<sys/msg.h> #include<string.h> struct msgbuf {long mtype;char mtext[128]; }; int main() {key_t key;key=ftok(".",'z');printf("key =%x\n",key);struct msgbuf sendbuf={888,"this is message from quen"};//888 是消息類型struct msgbuf readbuf;int msgid=msgget(key,IPC_CREAT|0777);if(msgid==-1){printf("creat fail\n");}msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),988,0);printf("return from get:%s\n",readbuf.mtext);msgctl(msgid,IPC_RMID,NULL);//IPC_RMID將消息隊列的鏈表從內(nèi)核中移除。一般最后一個寫NULL,第一個是隊列id。return 0; }

共享內(nèi)存
共享內(nèi)存(Shared Memory),指兩個或多個進程共享一個給定的存儲區(qū)。

特點:

共享內(nèi)存是最快的一種 IPC,因為進程是直接對內(nèi)存進行存取。因為多個進程可以同時操作,所以需要進行同步。信號量+共享內(nèi)存通常結(jié)合在一起使用,信號量用來同步對共享內(nèi)存的訪問。

思路:
(1)創(chuàng)建共享內(nèi)存、若已經(jīng)存在則直接打開
(2)映射將共享內(nèi)存映射到進程獨自的內(nèi)存空間
(3)數(shù)據(jù)交換
(4)釋放共享內(nèi)存
(5)干掉共享內(nèi)存
相關API

#include <sys/shm.h>// 創(chuàng)建或獲取一個共享內(nèi)存:成功返回共享內(nèi)存ID,失敗返回-1,共享內(nèi)存的大小必須以兆對齊。int shmget(key_t key, size_t size, int flag);// (映射)連接共享內(nèi)存到當前進程的地址空間:成功返回指向共享內(nèi)存的指針,失敗返回-1void *shmat(int shm_id, const void *addr, int flag);// 斷開與共享內(nèi)存的連接:成功返回0,失敗返回-1int shmdt(void *addr); // 控制共享內(nèi)存的相關信息:成功返回0,失敗返回-1int shmctl(int shm_id, int cmd, struct shmid_ds *buf);

當用shmget函數(shù)創(chuàng)建一段共享內(nèi)存時,必須指定其 size;而如果引用一個已存在的共享內(nèi)存,則將 size 指定為0 。

當一段共享內(nèi)存被創(chuàng)建以后,它并不能被任何進程訪問。必須使用shmat函數(shù)連接該共享內(nèi)存到當前進程的地址空間,連接成功后把共享內(nèi)存區(qū)對象映射到調(diào)用進程的地址空間,隨后可像本地空間一樣訪問。

shmdt函數(shù)是用來斷開shmat建立的連接的。注意,這并不是從系統(tǒng)中刪除該共享內(nèi)存,只是當前進程不能再訪問該共享內(nèi)存而已。

shmctl函數(shù)可以對共享內(nèi)存執(zhí)行多種操作,根據(jù)參數(shù) cmd 執(zhí)行相應的操作。常用的是IPC_RMID(從系統(tǒng)中刪除該共享內(nèi)存)。

寫端代碼

#include<stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include<stdlib.h> #include <string.h> //int shmget(key_t key, size_t size, int shmflg); int main() {int shmid;char* shmaddr;key_t key;key=ftok(".",1);shmaddr=(char*)malloc(1024*4);shmid=shmget(key,1024*4,IPC_CREAT|0666);//IPC_CREAT|0666 創(chuàng)建共享內(nèi)存,注明內(nèi)存權(quán)限可讀可寫if(shmid==-1){printf("creat fail\n");exit(-1);// 異常退出返回-1,正常退出返回0.}else{shmaddr=shmat(shmid,0,0);//第二個一般寫0,linux內(nèi)核為我們自動的安排共享內(nèi)存,第三個寫0,表示映射進來的共享內(nèi)存是可讀可寫的。printf("shmat ok\n");strcpy(shmaddr,"I am handsome");//將內(nèi)容寫入共享內(nèi)存sleep(5);shmdt(shmaddr);//將映射的地址放入,卸載共享內(nèi)存shmctl(shmid,IPC_RMID,0);//第三個參數(shù)用來存放卸載共享內(nèi)存時產(chǎn)生的信息,不關心就寫0.IPC_RMID刪除共享內(nèi)存printf("quit\n");}return 0; }

讀端代碼

#include<stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include<stdlib.h> #include <string.h> //int shmget(key_t key, size_t size, int shmflg); int main() {int shmid;char* shmaddr;key_t key;key=ftok(".",1);shmaddr=(char*)malloc(1024*4);shmid=shmget(key,1024*4,0);// 讀的時候只獲取不創(chuàng)建所以最后的代碼寫0.if(shmid==-1){printf("creat fail\n");exit(-1);}else{shmaddr=shmat(shmid,0,0);printf("shmat ok\n");printf("data is %s\n",shmaddr);shmdt(shmaddr);printf("quit\n");shmctl(shmid,IPC_RMID,0);}return 0; }

ipcs -m -------查看系統(tǒng)中有哪些共享內(nèi)存
ipcrm -m + 共享內(nèi)存ID號------刪除共享內(nèi)存

總結(jié)

以上是生活随笔為你收集整理的IPC 共享内存和 消息队列(发送、接收、移除)以及键值的生成的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。