IPC 共享內存和 消息隊列(發送、接收、移除)以及鍵值的生成

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

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

原型:

 #include <sys/msg.h>// 創建或打開消息隊列:成功返回隊列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);// 讀取消息:成功返回消息數據的長度,失敗返回-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將創建一個新的消息隊列:

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

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

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

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

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

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

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

接收代碼演示

#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];//信息數據存放
};
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分別表示創建隊列,和隊列的權限
//      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;
}

發送代碼演示

 <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將消息隊列的鏈表從內核中移除。一般最后一個寫NULL,第一個是隊列id。return 0;
}

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

特點:

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

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

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

當用shmget函數創建一段共享內存時,必須指定其 size;而如果引用一個已存在的共享內存,則將 size 指定為0 。

當一段共享內存被創建以后,它并不能被任何進程訪問。必須使用shmat函數連接該共享內存到當前進程的地址空間,連接成功后把共享內存區對象映射到調用進程的地址空間,隨后可像本地空間一樣訪問。

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

shmctl函數可以對共享內存執行多種操作,根據參數 cmd 執行相應的操作。常用的是IPC_RMID(從系統中刪除該共享內存)。

寫端代碼

#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   創建共享內存,注明內存權限可讀可寫if(shmid==-1){printf("creat fail\n");exit(-1);//  異常退出返回-1,正常退出返回0.}else{shmaddr=shmat(shmid,0,0);//第二個一般寫0,linux內核為我們自動的安排共享內存,第三個寫0,表示映射進來的共享內存是可讀可寫的。printf("shmat ok\n");strcpy(shmaddr,"I am handsome");//將內容寫入共享內存sleep(5);shmdt(shmaddr);//將映射的地址放入,卸載共享內存shmctl(shmid,IPC_RMID,0);//第三個參數用來存放卸載共享內存時產生的信息,不關心就寫0.IPC_RMID刪除共享內存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);// 讀的時候只獲取不創建所以最后的代碼寫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 -------查看系統中有哪些共享內存
ipcrm -m + 共享內存ID號------刪除共享內存

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272489.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272489.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272489.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DBA十大必備工具(SQLServer)

曾經和一些DBA和數據庫開發人員交流時&#xff0c;問他們都用過一些什么樣的DB方面的工具&#xff0c;大部分人除了SSMS和Profile之外&#xff0c;基本就沒有使用過其他工具了&#xff1b;誠然&#xff0c;SSMS和Profile足夠強大&#xff0c;工作的大部分內容都能通過它們搞定&…

linux 信號和信號量編程

對于 Linux來說&#xff0c;實際信號是軟中斷&#xff0c;許多重要的程序都需要處理信號。信號&#xff0c;為 Linux 提供了一種處理異步事件的方法。比如&#xff0c;終端用戶輸入了 ctrlc 來中斷程序&#xff0c;會通過信號機制停止一個程序。 信號概述 信號的名字和編號&…

安卓動畫基礎講解

//逐幀動畫 /** * 1.加入單張圖片 * 2.生成movie.xml整個圖片 * 3.代碼中使用圖片movie.xml */ iv(ImageView) findViewById(R.id.iv);// iv.setImageResource(R.drawable.movie);//為iv加載六張圖片// AnimationDrawable ad(AnimationDrawable) iv.getDrawable();//得到圖片給…

JS一些常用的類庫

一、返回上一頁&#xff08;history&#xff09;發覺有兩種用法&#xff1a;1、javascript:history.back(-1);2、javascript:history.go(-1);它們倆的區別是&#xff1a;history.back(-1):直接返回當前頁的上一頁&#xff0c;數據全部消息&#xff0c;返回新頁面history.go(-1)…

Linux上線程開發API概要(線程)

進程與線程 典型的UNIX/Linux進程可以看成只有一個控制線程&#xff1a;一個進程在同一時刻只做一件事情。有了多個控制線程后&#xff0c;在程序設計時可以把進程設計成在同一時刻做不止一件事&#xff0c;每個線程各自處理獨立的任務。 進程是程序執行時的一個實例&…

Redis學習筆記1-Redis數據類型

Redis數據類型 Redis支持5種數據類型&#xff0c;它們描述如下&#xff1a; Strings - 字符串 字符串是 Redis 最基本的數據類型。Redis 字符串是二進制安全的&#xff0c;也就是說&#xff0c;一個 Redis 字符串可以包含任意類型的數據&#xff0c;一個字符串最大為 512M 字節…

30個非常有趣的404錯誤頁面設計欣賞

當用戶訪問一個不存在的頁面的時候就會出現404錯誤頁面&#xff0c;這對用戶來說是很不友好的。所以很多網站都會去設計一個新穎的錯誤頁面&#xff0c;以吸引用戶繼續瀏覽其它的網頁內容。今天這篇文章就收集了30個非常有趣的404錯誤頁面設計欣賞&#xff0c;希望能帶給你靈感…

線程同步之互斥量加鎖解鎖 死鎖

與互斥鎖相關API 互斥量&#xff08;mutex&#xff09;從本質上來說是一把鎖&#xff0c;在訪問共享資源前對互斥量進行加鎖&#xff0c;在訪問完成后釋放互斥量上的鎖。對互斥量進行加鎖后&#xff0c;任何其他試圖再次對互斥量加鎖的線程將會被阻塞直到當前線程釋放該互…

游戲開發-從零開始 002

個人開發者的游戲大部分需要完成的內容&#xff1a; 1.完整的游戲玩法邏輯&#xff08;核心&#xff09; 2.UI 3.游戲關卡設計 4.游戲旁白 5.交互細節 6.游戲分享接口 7.游戲道具 8.游戲排行榜&#xff0c;游戲社區&#xff0c;如 GameCenter 9.游戲內購 如 remove Ads 10.廣告…

5 個最佳的 Linux 桌面環境

打算把每個桌面都試用一遍&#xff0c;但是那很費時間&#xff0c;而且確實有很多桌面環境可供選擇&#xff0c;這就是我發表“最優秀的 Linux 桌面以及他們的優缺點”的目的&#xff0c;本文告訴你在選擇桌面時需要注意些什么&#xff0c;讓我們開始吧。1. KDE我想從第五個說起…

線程條件控制實現線程的同步

與條件變量相關API 條件變量是線程另一可用的同步機制。條件變量給多個線程提供了一個會合的場所。條件變量與互斥量一起使用時&#xff0c;允許線程以無競爭的方式等待特定的條件發生。 條件本身是由互斥量保護的。線程在改變條件狀態前必須首先鎖住互斥量&#xff0c…

自定義能夠for each的類,C#,Java,C++,C++/cli的實現方法

自定義類能夠被for each&#xff0c;應該算是個老生常談的話題了&#xff0c;相關的資料都很多&#xff0c;不過這里整理總結主流語言的不同實現方式&#xff0c;并比較部分細節上的差異。 第一種語言&#xff0c;也是實現起來最簡單的Java語言。在Java里&#xff0c;要被for e…

SQL Server 2008 R2:快速清除日志文件的方法

本例&#xff0c;快速清理“students”數據庫的日志&#xff0c;清理后日志文件不足1M。USE [master] GO ALTER DATABASE students SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE students SET RECOVERY SIMPLE GO USE students GO--此處需要注意&#xff…

linux網絡編程之字節序

進程間通信 特點&#xff1a;依賴于內核&#xff0c;造成缺陷——無法實現多機通信。 網絡編程 地址&#xff1a;由IP地址和端口號構成&#xff0c;端口號用來判斷客戶端接入哪個服務器。 數據的交流&#xff1a;涉及到協議&#xff08;http&#xff0c;tcp&#xff0c;udp&…

Oracle查看表空間和表空間中的對象

select * from user_tables;--查詢所有用戶表 select username,default_tablespace from user_users;--查詢當前表空間select tablespace_name from dba_tablespaces;--查詢所有表空間select tablespace_name, sum(bytes)/1024/1024 from dba_data_files group by tablespace_n…

C#中DateTime.Ticks屬性及Unix時間戳轉換

DateTime.Ticks&#xff1a;表示0001 年 1 月 1 日午夜 12:00:00 以來所經歷的 100 納秒數&#xff0c;即Ticks的屬性為100納秒&#xff08;1Ticks 0.0001毫秒&#xff09;。Unix時間戳&#xff1a;是從1970年1月1日&#xff08;UTC/GMT的午夜&#xff09;開始所經過的秒數&am…

WebBrowser控件的常用方法、屬性和事件

1. 屬性屬性說明Application如果該對象有效&#xff0c;則返回掌管WebBrowser控件的應用程序實現的自動化對象(IDispatch)。如果在宿主對象中自動化對象無效&#xff0c;這個程序將返回WebBrowser 控件的自動化對象Parent返回WebBrowser控件的父自動化對象&#xff0c;通常是一…

二維碼高亮

// 二維碼高亮。http://blog.sina.com.cn/s/blog_a843a8850102uy6w.html 轉載于:https://www.cnblogs.com/muyushifang07/p/5114667.html

socket 網絡 編程

網絡編程場景 自己是客戶端站在5棟樓前&#xff0c;自己要找到5棟樓中的一座并進入某一間房間&#xff0c;這時第二座樓上有人在用漢語&#xff08;tcp/udp&#xff09;說話,我的ip地址&#xff08;樓號&#xff09;是…&#xff0c;我的端口號&#xff08;房間號&#xff09;是…

7個免費的Linux FTP客戶端工具

在Dropbox、YouSendIt、idrive以及許多這樣云存儲和共享工具的幫助下&#xff0c;我們在互聯網上發送和共享大型文件變得容易起來。所有這些網站都可以幫助你在互聯網上傳送文件&#xff0c;但如果你要分享龐大的數據&#xff0c;這依然是很復雜的事情。所以&#xff0c;你需要…