【Linux】System V信號量詳解以及semget()、semctl()和semop()函數講解

在這里插入圖片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃個人主頁 :阿然成長日記 👈點擊可跳轉
📆 個人專欄: 🔹數據結構與算法🔹C語言進階🔹C++🔹Liunx
🚩 不能則學,不知則問,恥于問人,決無長進
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

文章目錄

  • 前言:
  • 一、什么是臨界區和臨界資源?
  • 二、SystemV信號量引出
  • 三、什么是SystemV信號量?
  • 四、 SystemV信號量的創建和控制以及操作
    • 1.semget()函數:
    • 2.semctl()函數:
    • 3.semop()函數:

前言:

上一篇博客講解了System V共享內存,在最后說它的缺點時提到,他沒有提供進程同步機制,那么為了彌補這個缺點,所以引入了信號量sem機制。

一、什么是臨界區和臨界資源?

  • 臨界資源:多個進程共同使用的一份資源,例如共享內存就是一個臨界資源

  • 臨界區:不同進程內部,訪問臨界資源的那段代碼

二、SystemV信號量引出

  • 打個比方:這場電影一共有五十個位置,設置一個信號量n,n = 50;看電影的人必須買票,買一張票信號量n就會減一,當n=0時,也就代表資源已經耗盡,沒有位置了。但是如果有人退票的話,n會加1。買了票才能進入觀影。
    相應的,每一個進程想進入臨界資源,訪問臨界資源的一部分,不能讓進程直接去使用臨界資源(不能讓用戶直接去電影院搶占座位),而是先得申請 信號量(先得買票)。

這樣說的話,我們只需要一個int型的變量就可做到計數器的功能了,那還大費周章的提出一個信號量干嘛呢?

1.不是局部變量

  • 這個變量肯定不是局部變量,那么使用一個全局變量可以嗎?

2.不是全局變量

  • 如果使用全局變量,父子進程在申請信號量時,會發生寫時拷貝,導致這個變量父子進程各自一份,也不太行。

3.不在共享內存中

  • 那就使用最近剛剛學習的共享內存不就好了嗎。仔細思考也不可以。
  • 首先共享內存也就是說變量直接存儲在內存中。我們創建的幾個程序執行時是需要將指令放入cpu中進行執行。
  • 假設只看這個共享區的變量n,它的隨著一個進程執行過程如下
    1.將內存中的數據n加載到cpu的寄存器
    2.n–(分析&&執行指令)
    3.將cpu修改完畢的n寫回內存。
  • 一個進程執行流在執行的時候,在任何時刻都可能被切換 , 被切換的時候,會帶走自己的上下文數據(包括n),然后再被切回來的時候,再把自己的上下文數據寫入到cpu的寄存器中,繼續執行。
  • 這樣就有了一個問題:

假設有10個進程,分別為1,2,3,4…,9,10,而臨界資源一共只有5份,所以信號量n也為5.
假設1先申請信號量,但運氣不好執行完第一步,就被切走了,然后2,3,4,5,6都正常申請了信號量,此時信號量已經為0,后面7到10的進程都不能再申請了。
但此時1號又開始繼續執行,由于第一次進來時n是5,繼續執行第2,3步,n–為4,然后再寫回到內存,此時n從0變成了4,這不就差了嗎,明明都沒有資源了,結果信號量成了4,后面的進程又可以繼續申請,這樣肯定就出錯了。
所以n減減時,因為時序問題導致n有中間狀態,可能導致數據不一致、但如果n只有一行匯編,那么該操作就是原子的!

4.提出System V信號量

所以就提出了信號量機制


三、什么是SystemV信號量?

信號量的本質是:是一個描述臨界資源的計數器

System V信號量是一種在操作系統中提供的進程間通信(IPC)機制,用于實現進程之間的同步和互斥。它通過對計數器進行操作來控制資源的訪問。

System V信號量由一個整型的標識符(semaphore identifier)來標識,每個標識符對應著一個信號量集合(semaphore set)。信號量集合中可以包含多個單獨的信號量,每個信號量都有一個非負整數值。

四、 SystemV信號量的創建和控制以及操作

分別對一個semget()、semctl()和semop()

頭文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

1.semget()函數:

首先回顧一下ftok():


ftok()函數生成key
頭文件:

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

格式:

key_t ftok(const char *pathname, int proj_id);
  • 參數:
    pathname指針:一個字符串,用于標識一個文件的路徑名。通常會選擇一個已經存在的文件,因為 ftok() 函數將使用該文件的inode編號和 proj_id 參數通過算法來生成鍵值key。
    proj_id:一個整數,作為用于生成鍵的項目標識號。該參數通常取一個非負整數。
  • 返回值:成功則返回生成的鍵值,否則返回-1。

格式:

int semget(key_t key, int nsems, int semflg);

參數:

  • key:唯一key值,用于標識要創建或獲取的信號量集合。
    key值可以使用ftok()獲取

  • nsems:指定信號量集合中信號量的數量。你想創建幾個信號量。可以想象成一個數組。

  • semflg:標志參數,用于指定信號量的創建方式和訪問權限。有下面兩個選項

IPC_CREATE創建共享內存,如果底層已經存在,則獲取并返回;如果不存在,則創建共享內存然后再返回,
IPC_CREATE | IPC_EXCL如果底層不存在,則創建共享內存并返回;如果底層存在,則出錯返回。言外之意,如果返回成功,那么一定是一個全新的內存塊!

使用:
通過指定一個鍵值和其他參數,調用semget()函數可以創建一個新的信號量集合,或者獲取一個已經存在的信號量集合。

返回值:
返回值是一個信號量標識符(semaphore identifier),它用于后續對信號量集合的控制和操作

注意理清一個概念:semget()可以一次申請多個信號量(n1,n2.n3,),其中一個信號量n1就是一個計數器

2.semctl()函數:

int semctl(int semid, int semnum, int cmd, ...);

參數:

  • semid:信號量標識符,用于指定要操作的信號量集合。
  • semnum:注意與seget()區分清楚。指定具體的信號量在集合中的索引,用于標識要操作的信號量。
  • cmd:執行的控制命令,用于指定具體的操作。
  • arg:根據不同的命令,需要提供的參數。

下面是semctl函數cmd形參說明表

命令解 釋
IPC_STAT從信號量集上檢索semid_ds結構,并存到semun聯合體參數的成員buf的地址中
IPC_SET設置一個信號量集合的semid_ds結構中ipc_perm域的值,并從semun的buf中取出值
IPC_RMID從內核中刪除信號量集合
GETALL從信號量集合中獲得所有信號量的值,并把其整數值存到semun聯合體成員的一個指針數組中
GETNCNT返回當前等待資源的進程個數
GETPID返回最后一個執行系統調用semop()進程的PID
GETVAL返回信號量集合內單個信號量的值
GETZCNT返回當前等待100%資源利用的進程個數
SETALL與GETALL正好相反
SETVAL用聯合體中val成員的值設置信號量集合中單個信號量的值

用法
semctl()函數用于控制和管理信號量集合。
可以通過指定不同的控制命令(cmd)來實現不同的操作,例如設置信號量的初始值獲取或改變信號量的值,以及刪除信號量集合等。
具體的參數(如arg)根據不同的命令而有所不同。

3.semop()函數:

int semop(int semid, struct sembuf *sops, unsigned nsops);

參數:

  • semid:信號量標識符,用于指定要操作的信號量集合。由seget()獲取
  • sops:指向一個sembuf結構體數組的指針,包含了一組操作。此結構的具體說明如下:(里面的注釋很重呀)
struct sembuf {short semnum; 指定要操作的信號量在集合中的索引,從0開始計數。short op;指定要執行的操作。
如果sem_op的值大于0,則表示進行V(釋放)操作,即增加信號量的值。
如果sem_op的值小于0,則表示進行P(等待)操作,即減少信號量的值。
如果sem_op的值等于0,則表示進行Z(零)操作,如果信號量的值為0,則等待。該操作通常用于同步操作,以等待某個特定條件的發生。short flag;  用于指定操作的標志。
IPC_NOWAIT:如果無法進行操作(例如信號量的值為0且sem_op為負數),則立即返回,不進行等待。
SEM_UNDO:系統在進程意外終止時,會自動撤銷該進程對信號量的操作,以避免死鎖。};
  • nsops:指定操作的數量。

作用: 用于對指定信號量集【semid】當中的指定數量的信號量【nsops:常常設置為1】,對它做操作【sembuf *sops】

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

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

相關文章

Kotlin構造函數

目錄 構造函數類型 主構造函數 成員變量設置 私有化操作 次級構造函數 構造函數類型 主構造函數&#xff08;主構造器&#xff09;——只能有一個次構造函數&#xff08;次構造器&#xff09;——可以是多個 主構造函數 構造器 constructor關鍵字前 無注解或修飾符作用&…

性能監控的革命:Eureka引領分布式服務監控新紀元

性能監控的革命&#xff1a;Eureka引領分布式服務監控新紀元 引言 在微服務架構中&#xff0c;服務的分布式性能監控對于維護系統健康和優化用戶體驗至關重要。Eureka作為Netflix開源的服務發現框架&#xff0c;為服務的注冊與發現提供了強大支持&#xff0c;而結合其他工具&…

數字化轉型:企業法務管理的未來發展 ???

在數字化浪潮的推動下&#xff0c;企業法務管理正經歷著前所未有的變革。傳統的法務工作模式在數據處理、合同審查、風險評估等方面逐漸顯得力不從心。面對這一挑戰&#xff0c;企業法務管理的數字化轉型成為提升效率、保障合規、優化法律服務的必然選擇。 數字化轉型涉及到法…

HTML(30)——動畫

動畫 實現步驟 定義動畫 keyframes 動畫名稱{ from{} to{} } keyframes 動畫名稱{ 0%{} 10%{} .... 100%{} } 2.使用動畫 animation:動畫名稱 動畫花費時間; 示例&#xff1a;盒子的寬度從200變到400px&#xff0c;兩個狀態一般用from to的形式 <style>.box {width: …

解析Xml文件并修改QDomDocument的值

背景&#xff1a; 我需要解決一個bug&#xff0c;需要我從xml中讀取數據到QDomDocument&#xff0c;然后獲取到我想要的目標信息&#xff0c;然后修改該信息。 ---------------------------------------------------------------------------------------------------------…

各大常用代碼編輯器的快捷鍵集合

visualstudio2017 快捷鍵 多行注釋 crtl / 取消多行注釋crtl Q 代碼跳轉返回 crtl /- visualcode快捷鍵 代碼跳轉返回 crtl 左鍵/右鍵 androidstudio快捷鍵 代碼跳轉返回 crtl alt 左鍵/右鍵

VUE中ECharts提示框tooltip自動切換

目錄 前言1導入插件2定義參數3 插件API 前言 使用VUE開發的數據大屏統計&#xff0c;又需要將 echarts的提示框 tooltip 實現自動切換&#xff0c;網上有個很簡單的插件&#xff08;echarts-tooltip-auto-show&#xff09;&#xff0c;使用教程簡單分享給大家。 自動每隔幾秒切…

哦華為倉頡語言

本來我不太想說的&#xff0c;奈何有不少粉絲提問提到了這語言&#xff0c;目前的情況我不透露太多&#xff0c;看過這課程C實現一門計算機編程語言到手擼虛擬機實戰的懂的自然懂。 在互聯網領域幾乎大部分應用軟件運行在X86 LINUX上居多&#xff0c;如果你有問題可以先學習這…

多版本python環境中,讓python3固定指向其中一個python可執行文件

如果你只安裝一個python環境&#xff0c;那么一般可執行文件名就叫python.exe和pythonw.exe 但是如果你有多個python環境時&#xff0c;可執行文件名是需要進行修改的&#xff0c;使得在安裝庫和調用時能夠分辨python環境&#xff0c;比如我的電腦中裝有python3.10和python2.x …

Transformer模型論文解讀、源碼分析和項目實踐

本文是ChatGPT系列的開篇之作&#xff0c;為什么吧Transformer放到這里呢&#xff0c;因為不管是chatgpt-1&#xff0c; chatgpt-2&#xff0c; chatgpt-3都是以Transformer作為底層基礎來實現&#xff0c;相當于chatgpt系列的老祖先了。如果想要深入的了解清楚chatgpt的來龍去…

AcWing 4173. 線段 (貪心)

數軸上有 n 條線段&#xff0c;選取其中 k 條線段使得這 k&#x1d458; 條線段兩兩沒有重合部分&#xff0c;問 k 最大為多少。 輸入格式 第一行為一個正整數 n&#xff1b; 在接下來的 n 行中&#xff0c;每行有 2 個數 ai,bi&#xff0c;描述每條線段的左右端點坐標。 輸…

BUUCTF[堆][of_by_one]

堆中of_by_one 介紹&#xff1a; 嚴格來說 off-by-one 漏洞是一種特殊的溢出漏洞&#xff0c;off-by-one 指程序向緩沖區中寫入時&#xff0c;寫入的字節數超過了這個緩沖區本身所申請的字節數并且只越界了一個字節。溢出字節為可控制任意字節 &#xff1a;通過修改大小(size…

token無感刷新方法

1.這里推薦去看這個老師的視頻,我的方案都是根據他的視頻來的視頻地址 2.這邊使用的工具是axios import axios from axios const service axios.create({baseURL: ,headers: {Authorization: token 你自己的token,},timeout: 1000 * 60, })// 攔截響應 service.interceptors…

Spring AOP源碼篇四之 數據庫事務

了解了Spring AOP執行過程&#xff0c;再看Spring事務源碼其實非常簡單。 首先從簡單使用開始, 演示Spring事務使用過程 Xml配置&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema…

【北京迅為】《i.MX8MM嵌入式Linux開發指南》-第一篇 嵌入式Linux入門篇-第十六章 Linux 第一個程序 HelloWorld

i.MX8MM處理器采用了先進的14LPCFinFET工藝&#xff0c;提供更快的速度和更高的電源效率;四核Cortex-A53&#xff0c;單核Cortex-M4&#xff0c;多達五個內核 &#xff0c;主頻高達1.8GHz&#xff0c;2G DDR4內存、8G EMMC存儲。千兆工業級以太網、MIPI-DSI、USB HOST、WIFI/BT…

S271系列RTU在旅游景區人流監控中的應用案例

S271系列RTU在旅游景區人流監控中的應用案例 隨著全球旅游業的迅猛發展&#xff0c;旅游景區的管理者越來越關注如何利用先進的技術手段提升游客體驗、優化管理效率以及確保安全。S271系列RTU作為一款先進的無線工業物聯網設備&#xff0c;在旅游景區的人流監控中展現出了其獨…

數據結構:順序表+鏈表

數據結構&#xff1a;順序表鏈表 一。順序表&#xff1a; 首先在了解順序表和鏈表之前&#xff0c;先了解一下線性表&#xff0c;**線性表&#xff08;linear list&#xff09;**是n個具有相同特征元素的有限序列 &#xff0c;在邏輯上是線性結構&#xff0c;也就是一條連續的…

自動化升級:Conda包依賴的智能更新策略

自動化升級&#xff1a;Conda包依賴的智能更新策略 引言 在科學研究和軟件開發中&#xff0c;依賴管理是確保項目順利進行的關鍵環節。Conda作為流行的包管理器&#xff0c;提供了強大的依賴更新功能&#xff0c;幫助用戶自動化和簡化依賴項的更新過程。本文將深入探討如何在…

WPF依賴附加屬性

依賴附加屬性的定義 基本過程&#xff1a;聲明、注冊、包裝 依賴附加屬性必須在依賴對象&#xff0c;附加屬性不一定&#xff0c;關注的是被附加的對象是否是依賴對象 快捷方式&#xff1a;propa tab 關鍵字&#xff1a;RegisterAttached // 方法封裝 public static int …

Unity3d C#實現基于UGUI ScrollRect的輪播圖效果功能(含源碼)

前言 輪播功能是一種常見的頁面組件&#xff0c;用于在頁面中顯示多張圖片/素材并自動或手動進行切換&#xff0c;以提高頁面的美觀度和用戶體驗。主要的功能是&#xff1a;自動/手動切換;平滑的切換效果;導航指示器等。可惜Unity的UGUI系統里沒有現成的實現該功能&#xff0c…