Linux信號【systemV】

目錄

前言

正文:

1消息隊列

1.1什么是消息隊列??

1.2消息隊列的數據結構?

1.3消息隊列的相關接口?

1.3.1創建?

1.3.2釋放?

1.3.3發送?

1.3.4接收?

1.4消息隊列補充

2.信號量?

2.1什么是信號量?

2.2互斥相關概念?

2.3信號量的數據結構

2.4信號量相關接口?

2.4.1創建?

2.4.2釋放

2.4.3操作

2.5信號量補充

3.深入理解 System V通信方式?

總結:



前言

在 System V 通信標準中,還有一種通信方式:消息隊列,以及一種實現互斥的工具:信號量;隨著時代的發展,這些陳舊的標準都已經較少使用了,但作為 IPC 中的經典知識,我們可以對其做一個簡單了解,擴展 IPC 的知識棧,尤其是 信號量,可以通過它,為以后多線程學習中 POSIX 信號量的學習做鋪墊

正文:

1消息隊列

1.1什么是消息隊列??

?消息隊列(Message Queuing)是一種比較特殊的通信方式,它不同于管道與共享內存那樣借助一塊空間進行數據讀寫,而是?在系統中創建了一個隊列,這個隊列的節點就是數據塊,包含類型和信息

  • 假設現在進程 A、B 想要通過消息隊列進行通信,首先創建一個消息隊列
  • 然后進程 A 將自己想要發送給進程 B 的信息打包成數據塊(其中包括發送方的信息),將數據塊添加至消息隊列隊尾處
  • 進程 B 同樣也可以向消息隊列中添加數據塊,同時也會從消息隊列中捕獲其他進程的數據塊,解析后進行讀取,這樣就完成了通信

?

?

遍歷消息隊列時,存數據塊?還是?取數據塊?取決于?數據塊中的類型?type

注意:?消息隊列跟共享內存一樣,是由操作系統創建的,其生命周期不隨進程,因此在使用結束后需要刪除

下面有關于消息隊列詳解的文章

?

  • 《什么是消息隊列》
  • 《消息隊列詳解》

1.2消息隊列的數據結構?

同屬于?System V?標準,消息隊列也有屬于自己的數據結構

msg?表示?消息隊列

struct msqid_ds
{struct ipc_perm msg_perm;	/* Ownership and permissions */time_t msg_stime;			/* Time of last msgsnd(2) */time_t msg_rtime;			/* Time of last msgrcv(2) */time_t msg_ctime;			/* Time of last change */unsigned long __msg_cbytes; /* Current number of bytes in queue (nonstandard) */msgqnum_t msg_qnum;			/* Current number of messages in queue */msglen_t msg_qbytes;		/* Maximum number of bytes allowed in queue */pid_t msg_lspid;			/* PID of last msgsnd(2) */pid_t msg_lrpid;			/* PID of last msgrcv(2) */
};

?和?共享內存?一樣,其中?struct ipc_perm?中存儲了?消息隊列的基本信息,具體包含內容如下:

struct ipc_perm
{key_t __key;		  /* Key supplied to msgget(2) */uid_t uid;			  /* Effective UID of owner */gid_t gid;			  /* Effective GID of owner */uid_t cuid;			  /* Effective UID of creator */gid_t cgid;			  /* Effective GID of creator */unsigned short mode;  /* Permissions */unsigned short __seq; /* Sequence number */
};

可以通過?man msgctl?查看函數使用手冊,其中就包含了?消息隊列?的數據結構信息

1.3消息隊列的相關接口?

?論標準的重要性,消息隊列的大小接口風格與共享內存一致,都是出自?System V?標準

1.3.1創建?

?使用?msgget?函數創建?消息隊列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);

關于?msgget?函數

?

與?共享內存?的?shmget?可以說是十分相似了,關于?ftok?函數計算?key?值,這里就不再闡述,可以在這篇文章中學習 《Linux進程間通信【共享內存】》

簡單使用函數?msgget?創建?消息隊列,并使用?ipcs -q?指令查看資源情況

?

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>using namespace std;int main()
{//創建消息隊列int n = msgget(ftok("./", 668), IPC_CREAT | IPC_EXCL | 0666);if(n == -1){cerr << "msgget fail!" << endl;exit(1);}return 0;
}

程序運行后,創建出了一個?msqid?為?0?的消息隊列

因為此時并?沒有使用消息隊列進行通信,所以已使用字節?used-bytes?和 消息數?messages?都是?0

注意:

  • 消息隊列在創建時,也需要指定創建方式:IPC_CREATIPC_EXCL權限?等信息
  • 消息隊列創建后,msqid也是隨機生成的,大概率每次都不一樣
  • 消息隊列生命周期也是隨操作系統的,并不會因進程的結束而釋放
1.3.2釋放?

?

消息隊列也有兩種釋放方式:通過指令釋放、通過函數釋放

釋放指令:ipcrm -q msqid?釋放消息隊列,其他?System V?通信資源也可以這樣釋放

  • ipcrm -m shmid?釋放共享內存
  • ipcrm -s semid?釋放信號量集

?

釋放函數:msgctl(msqid, IPC_RMID, NULL)?釋放指定的消息隊列,跟?shmctl?刪除共享內存一樣

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgctl(int msqid, int cmd, struct msqid_ds *buf);

?關于?msgctl?函數

?簡單回顧下參數2部分可傳遞參數:

?

  • IPC_RMID?表示刪除共享內存
  • IPC_STAT?用于獲取或設置所控制共享內存的數據結構
  • IPC_SET?在進程有足夠權限的前提下,將共享內存的當前關聯值設置為?buf?數據結構中的值

同樣的,消息隊列 = 消息隊列的內核數據結構(struct msqid_ds) + 真正開辟的空間

1.3.3發送?

?利用消息隊列發送信息,即?將信息打包成數據塊,入隊尾,所使用函數為?msgsnd

?

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

?關于?msgsnd?函數

?

?參數2 表示待發送的數據塊,這顯然是一個結構體類型,需要自己定義,結構如下:

?

struct msgbuf
{long mtype;    /* message type, must be > 0 */char mtext[1]; /* message data */
};

mtype?就是傳說中數據塊類型,據發送方而設定;mtex?是一個比較特殊的東西:柔性數組,其中存儲待發送的?信息,因為是?柔性數組,所以可以根據?信息?的大小靈活調整數組的大小

1.3.4接收?

?消息發送后,總得接收吧,既然發送是往隊尾中添加數據塊,那么接收就是?從隊頭中取數據塊,假設所取數據塊為自己發送的,那么就不進行操作,其他情況則取出數據塊,使用?msgrcv?函數接收信息

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

關于?msgrcv?函數

同樣的,接收的數據結構如下所示,也包含了?類型?和?柔性數組

?

struct msgbuf
{long mtype;    /* message type, must be > 0 */char mtext[1]; /* message data */
};

1.4消息隊列補充

?System V?版的 消息隊列 使用起來比較麻煩,并且過于陳舊,現在已經較少使用了,所以我們不必對其進行深究,知道個大概就行了,如果實際中真遇到了,再查文檔也不遲


2.信號量?

2.1什么是信號量?

?信號量(semaphore)一種特殊的工具,主要用于實現?同步和互斥

信號量?又稱?信號燈,是各大高校《操作系統》課程中老師提及的高頻知識點,往往伴隨著?P、V?操作出現,但大多數老師都只是提及了基本概念,并未對?信號量?的本質及使用場景作出詳細講解

在正式學習?信號量?相關知識前,需要先簡單了解下?互斥相關四個概念,為后續?多線程中信號量的學習作鋪墊(重點)

2.2互斥相關概念?

1、并發?是指系統中同時存在多個獨立的活動單元

  • 比如在多線程中,多個執行流可以同時執行代碼,可能訪問同一份共享資源

2、互斥?是指同一時刻只允許一個活動單元使用共享資源

  • 即在任何一個時刻,都只允許一個執行流進行共享資源的訪問(可以通過加鎖實現)

3、臨界資源?與?臨界區,多執行流環境中的共享資源就是?臨界資源,涉及?臨界資源?操作的代碼區間即?臨界區

  • 在多線程環境中,全局變量就是?臨界資源,對全局變量的修改、訪問代碼屬于?臨界區

4、原子性:只允許存在 成功 和 失敗 兩種狀態

  • 比如對變量的修改,要么修改成功,要么修改失敗,不會存在修改一半被切走的狀態

?所以?互斥?是為了解決?臨界資源 在多執行流環境中的并發訪問問題,需要借助?互斥鎖 或 信號量?等工具實現?原子操作,實現?互斥

?

?

關于互斥鎖(mutex) 的相關知識在?多線程?中介紹,現在先來學習?信號量,搞清楚它是如何實現?互斥?的

2.3信號量的數據結構

?下面來看看?信號量?的數據結構,通過?man semctl?進行查看

?sem?表示?信號量

struct semid_ds
{struct ipc_perm sem_perm; /* Ownership and permissions */time_t sem_otime;         /* Last semop time */time_t sem_ctime;         /* Last change time */unsigned long sem_nsems;  /* No. of semaphores in set */
};

System V?家族基本規矩,struct ipc_perm?中存儲了?信號量的基本信息,具體包含內容如下:

?

struct ipc_perm
{key_t __key;          /* Key supplied to semget(2) */uid_t uid;            /* Effective UID of owner */gid_t gid;            /* Effective GID of owner */uid_t cuid;           /* Effective UID of creator */gid_t cgid;           /* Effective GID of creator */unsigned short mode;  /* Permissions */unsigned short __seq; /* Sequence number */
};

?顯然,無論是 共享內存、消息隊列、信號量,它們的 ipc_perm 結構體中的內容都是一模一樣的,結構上的統一可以帶來管理上的便利,具體原因可以接著往下看

2.4信號量相關接口?

2.4.1創建?

?信號量的申請比較特殊,一次可以申請多個信息量,官方稱此為?信號量集,所使用函數為?semget

?

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);

關于?semget?函數

除了參數2,其他基本與另外倆兄弟一模一樣,實際傳遞時,一般傳?1,表示只創建一個?信號量

使用函數創建?信號量集,并通過指令?ipcs -s?查看創建的?信號量集?信息

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>using namespace std;int main()
{//創建一個信號量int n = semget(ftok("./", 668), 1, IPC_CREAT | IPC_EXCL | 0666);if(n == -1){cerr << "semget fail!" << endl;exit(1);}return 0;
}

程序運行后,創建了一個?信號量集nsems?為?1,表示在當前?信號量集?中只有一個?信號量

  • 信號量集在創建時,也需要指定創建方式:IPC_CREATIPC_EXCL權限?等信息
  • 信號量集創建后,semid也是隨機生成的,大概率每次都不一樣
  • 信號量集生命周期也是隨操作系統的,并不會因進程的結束而釋放
2.4.2釋放

老方法: 指令釋放:直接通過指令?ipcrm -s semid?釋放信號量集(略)

通過函數釋放:semctl(semid, semnum, IPC_RMID),信號量中的控制函數有一點不一樣

?

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, ...);

?關于?semctl?函數

注意:

  • 參數2 表示信號量集中的某個信號量編號,從?1?開始編號
  • 參數3 中可傳遞的動作與共享內存、消息隊列一致
  • 參數4 就像?printf?和?scanf?中最后一個參數一樣,可以靈活使用
2.4.3操作

信號量的操縱比較ex,也比較麻煩,所以僅作了解即可

使用?semop?函數對?信號量?進行諸如?+1-1?的基本操作

?

 #include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semop(int semid, struct sembuf *sops, unsigned nsops);

?關于?semop?函數

重點在于參數2,這是一個結構體,具體成員如下:

unsigned short sem_num;  /* semaphore number */
short          sem_op;   /* semaphore operation */
short          sem_flg;  /* operation flags */

其中包含信號量編號、操作等信息,需要我們自己設計出一個結構體,然后傳給?semop?函數使用

可以簡單理解為:sem_op?就是要進行的操作,如果將?sem_op?設為?-1,表示信號量?-1(申請),同理?+1?表示信號量?+1(歸還)

2.5信號量補充

?

信號量 是實現 互斥 的其中一種方法,具體表現為:資源申請,計數器 -1,資源歸還,計數器 +1,只有在計數器不為 0 的情況下,才能進行資源申請,可以設計 二元信號量 實現 互斥

System V 中的 信號量 操作比較麻煩,但 信號量 的思想還是值得一學的,等后面學習 多線程 時,也會使用 POSIX 中的 信號量 實現 互斥,相比之下,POSIX 版的信號量操作要簡單得多,同時應用也更為廣泛

因為 信號量 需要被多個獨立進程看到,所以 信號量 本身也是 臨界資源,不過它是 原子 的,所以可以用于 互斥

多個獨立進程看到同一份資源,這就是 IPC 的目標,所以 信號量 被劃分至進程間通信中

?


3.深入理解 System V通信方式?

?不難發現,共享內存、消息隊列、信號量的數據結構基本一致,并且都有同一個成員?struct ipc_perm,所以實際對于?操作系統?來說,對?System V?中各種方式的描述管理只需要這樣做

  • 將 共享內存、消息隊列、信號量對象描述后,統一存入數組中
  • 再進行指定對象創建時,只需要根據 ipc_id_arr[n]->__key 進行比對,即可當前對象是否被創建!
  • 因為 struct shmid_ds 與 struct ipc_perm shm_perm 的地址一致(其他對象也一樣),所以可以對當前位置的指針進行強轉:((struct shmid_ds)ipc_id_arr[0]) 即可訪問 shmid_ds 中的成員,這不就是多態中的虛表嗎?

這樣一來,操作系統可以只根據一個地址,靈活訪問 兩個結構體中的內容,比如 struct ipc_perm shm_perm 和 struct shmid_ds,并且操作系統還把多種不同的對象,描述融合入了一個 ipc_id_arr 指針數組中,真正做到了 高效管理

注:默認 ipc_id_arr[n] 訪問的是 struct ipc_perm 中的成員

注:上述圖示只是一個草圖,目的是為了輔助理解原理,并非操作系統中真實樣貌

操作系統在進行比較判斷時,如何判斷類型呢?

這就是操作系統設計的巧妙之處了,ipc_id_arr 沒那么簡單,它會存儲對象的相應類型信息
通過下標(id) 訪問對象,這與文件系統中的機制不謀而合,不過實現上略有差異,間接導致 System V 的管理系統被邊緣化(歷史選擇了文件系統)

shmid、msqid 和 semid 都是 ipc_id_arr 的下標,為什么值很大呢?

在進行查找時,會將這些 id % 數組大小 進行轉換,確保不會發生越界,事實上,這個值與開機時間有關,開機越長,值越大,當然到了一定程度后,會重新輪回

總結:

上面就是關于信號量部分的內容,有個大概了解就行。

?

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

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

相關文章

lambda表達式 —— 過濾再排序未生效問題排查

背景 項目中有個場景&#xff0c;需要將一個列表先按要求過濾&#xff0c;再根據某字段排序。圖方便使用lambda表達式修改原列表將過濾和排序邏輯寫到一行&#xff0c;打印輸出列表發現過濾未生效。 代碼示例&#xff1a; List<Long> productIdList Arrays.asList(1L);…

向爬蟲而生---Redis 探究篇4<Redis主從復制(1)>

前言: 當涉及到Redis的高可用性和數據冗余時&#xff0c;主從復制是一個非常重要的概念。 在現代應用程序的開發中&#xff0c;數據的可靠性和高可用性是至關重要的。當涉及到數據冗余和故障恢復時&#xff0c;Redis主從復制成為一個必不可少的工具和技術。Redis主從復制是一…

藍橋杯-單片機組基礎5——外部中斷與LED的控制(附小蜜蜂課程代碼)

藍橋杯單片機組備賽指南請查看這篇文章&#xff1a;戳此跳轉藍橋杯備賽指南文章 本文章針對藍橋杯-單片機組比賽開發板所寫&#xff0c;代碼可直接在比賽開發板上使用。 型號&#xff1a;國信天長4T開發板&#xff08;綠板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

自學軟件測試怎么學?

軟件測試是一個變得越來越受歡迎的行業&#xff0c;在IT行業里面&#xff0c;也是初學比較容易的。但對小白而言&#xff0c;怎樣學習才能做到快速入門&#xff0c;少走彎路呢&#xff1f; 步驟一&#xff1a;初學學軟件測試&#xff0c;要先搞懂這種問題 要想進入到軟件測試…

Android Duplicate class 排除重復類

一、起因&#xff1a; 在迭代開發的時候&#xff0c;發現2個ijk很多類重復。但又2個庫實現的功能是不一樣&#xff0c;目前不能合并。但又想保留2個功能。需要排除其中一個庫。 二、報錯如何下圖&#xff1a; 三、解決方法&#xff1a; 3.1 在terminal 也就是命令行處輸入 …

Golang 并發機制 CSP模型

Golang 并發機制 CSP模型 1 前言 go語言的最大兩個亮點&#xff0c;一個是 goroutine &#xff0c;一個就是 chan 了。二者合體的典型應用CSP&#xff0c;基本就是大家認可的并行開發神器&#xff0c;簡化了并行程序的開發難度&#xff0c;我們來看一下CSP。 2 CSP是什么 C…

在Windows 11中運行磁盤清理工具的9種方法,總有一種適合你

自Windows98以來,微軟在操作系統中包含了一個內置的清理工具。當用戶轉向第三方清理應用程序時,這個值得信賴的實用程序站穩了腳跟。微軟甚至宣布,第三方應用程序幾乎毫無用處,刪除注冊表項不是一個好主意。 磁盤清理工具可以幫助刪除臨時文件、舊的更新日志、縮略圖緩存和…

git安裝與使用4.3

一、git的安裝 1、下載git包 下載git包url&#xff1a;https://git-scm.com/download/win 下載包分為&#xff1a;64位和32位 2、點擊安裝包 2、選擇安裝路徑 3、 點擊下一步 4、點擊next 5、點擊next 6、點擊next 7、 8、 9、 10、 11、 12、在桌面空白處&#xff0c;右鍵…

【SpringBoot】測試單元使用多線程

&#x1f4dd;個人主頁&#xff1a;五敷有你 &#x1f525;系列專欄&#xff1a;SpringBoot ??穩重求進&#xff0c;曬太陽 問題產生 今天學習了樂觀鎖&#xff0c;但在測試單元執行多線程的時候出現了問題&#xff0c;多線程并沒有直接結果 在控制臺沒有任何輸出…

KubeSphere平臺安裝系列之二【Linux單節點部署KubeSphere】(2/3)

**《KubeSphere平臺安裝系列》** 【Kubernetes上安裝KubeSphere&#xff08;親測–實操完整版&#xff09;】&#xff08;1/3&#xff09; 【Linux單節點部署KubeSphere】&#xff08;2/3&#xff09; 【Linux多節點部署KubeSphere】&#xff08;3/3&#xff09; **《KubeS…

RocketMQ學習筆記一

課程來源&#xff1a;002-MQ簡介_嗶哩嗶哩_bilibili &#xff08;尚硅谷老雷&#xff0c;時長19h&#xff09; 第1章 RocketMQ概述 1. MQ是什么&#xff1f; 2. MQ用途有哪些&#xff1f; 限流削峰&#xff1b;異步解耦&#xff1b;數據收集。 3. 常見MQ產品有哪些&對比…

Kaggle競賽之Titanic存活預測2

提高代碼規范性&#xff0c;基于上一個 baseline 的提高 import pandas as pd from sklearn.preprocessing import LabelBinarizer from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split#數據劃分方法 from sklearn.ensem…

哪個超聲波清洗機品牌值得入手?銷量榜品牌值得選購!

在科技日益發展的今天&#xff0c;超聲波清洗技術以其高效、便捷和深度清潔的特點&#xff0c;已經深入到生活的諸多領域&#xff0c;從精密儀器到珠寶首飾&#xff0c;從眼鏡框到假牙&#xff0c;甚至是廚房用品的日常護理&#xff0c;都能見到超聲波清洗機的身影。面對市場上…

無人機兩次飛行的圖像數據配準與幾何校正方法研究

標題: 無人機兩次飛行的圖像數據配準與幾何校正方法研究 摘要: 本文研究了利用無人機獲取的兩次飛行的圖像數據進行配準與幾何校正的方法。無人機航拍技術在地理信息獲取和空間數據應用中具有重要意義,但由于飛行條件、攝影設備和環境等因素的影響,同一區域的不同飛行任務…

【基頻提取算法-YIN】

本文對基頻提取算法 YIN 做以介紹。如有表述不當之處歡迎批評指正。歡迎任何形式的轉載&#xff0c;但請務必注明出處。 文章目錄 1. 引言2. YIN 各模塊代碼講解2.1. 差分函數的實現2.2. 累積均值歸一化差分函數的實現2.3. 絕對閾值2.4. 拋物線插值2.5. 最優局部估計 3. 總結 1…

免殺實戰-EDR對抗

文章目錄 殺軟分析BOF.NET 殺軟分析 x64dgb簡單調試發現該edr在r3環對ntdll.dll和kernel32.dll關鍵函數均存在hook&#xff0c;這里硬盤讀取原來的dll進行重新加載&#xff0c;原理如圖 loader // dllmain.cpp : 定義 DLL 應用程序的入口點。 #include "pch.h" #in…

DSI2協議之BTA行為理解

概念: DSI協議spec支持總線控制權在master和slave之間發生交換,即通過bus turn around來實現; BUS TURN AROUND: BTA 的實現是通過controller—>cdphy的turnrequest信號來實現; 關于控制器發出turnrequest給phy,phy通過lvds/trio線輸出turnaround sequence如下圖中…

LeetCode刷題筆記之二叉樹(四)

一、二叉搜索樹的應用 1. 700【二叉搜索樹中的搜索】 題目&#xff1a; 給定二叉搜索樹&#xff08;BST&#xff09;的根節點 root 和一個整數值 val。你需要在 BST 中找到節點值等于 val 的節點。 返回以該節點為根的子樹。 如果節點不存在&#xff0c;則返回 null 。代碼&a…

BUGKU 本地管理員

打開環境&#xff0c;先F12查看看到一串代碼。Base64解碼一下&#xff0c;得到的應該是密碼&#xff0c;然后輸入admin | test123試一下 使用BP抓包&#xff0c;修改XFF&#xff0c;得到flag

將鏡像上傳到私有鏡像倉庫Harbor

首先你需要安裝Harbor服務&#xff1a; https://blog.csdn.net/qq_50247813/article/details/136388229 客戶端已經安裝docker&#xff1a; https://docs.docker.com/engine/install/centos/ 在docker客戶端登錄 Harbor 我的Harbor 服務器地址&#xff1a; 192.168.44.161 賬號…