Linux程序間通訊 訊號量

2021-09-01 12:01:37 字數 3706 閱讀 6494

訊號量概述

在多工作業系統環境下,多個程序/執行緒會同時進行。多工可能為了完成同乙個目標會相互協作,這樣就形成了任務之間的同步關係。同樣,不同任務之間為了爭奪有限的系統資源(硬體或軟體資源)會進入競爭狀態。 任務間的互斥與同步關係存在的根源在於臨界資源。臨界資源:是指在同一時刻只允許有限個(通常只有乙個)操作的資源。訪問臨界資源的**成為臨界區。 訊號量是用來解決程序/執行緒之間同步與互斥問題的一種通訊機制,包括乙個稱為訊號量的變數和在該訊號量下等待資源程序等待佇列,以及對訊號量進行的兩個原子操作(pv操作)。訊號量常常被用做乙個鎖機制,在某個程序正對特定資源進行操作時,訊號量可以防止其他程序去訪問它 pv原子操作(訊號量工作原理)

1. p(操作):如果有可用資源(訊號量值大於0),則占用乙個資源(訊號量值減1,進入臨界區**);如果沒有可用資源(訊號量值等於0),則被阻塞,直到系統將資源分配給該任務(進入等待佇列,一直等待到有資源是被喚醒)。

2. v(操作):如果在該訊號量的等待佇列中有任務在等待資源,則喚醒乙個阻塞任務。如果沒有等待它,則釋放乙個資源(訊號量值加1)。 訊號量資料結構

核心為每乙個訊號量集合設定了乙個semid_ds機構體

union  semun;

sem_num:操作訊號在訊號集中的編號,第乙個訊號的編號是0。

sem_op:sem_op值:

(1)若sem_op為正,這對應於程序釋放占用的資源數。sem_op值加到訊號量的值上。(v操作)

(2)若sem_op為負,這表示要獲取該訊號量控制的資源數。訊號量值減去sem_op的絕對(p操作)

(3)若sem_op為0,這表示呼叫程序希望等待到該訊號量值變成0

◆如果訊號量值小於sem_op的絕對值(資源不能滿足要求),則:

(1)若指定了ipc_nowait,則semop()出錯返回eagain。

(2)若未指定ipc_nowait,則訊號量的semncnt值加1(因為呼叫程序將進 入休眠狀態),後呼叫程序被掛起直至:

①此訊號量變成大於或等於sem_op的絕對值;

②從系統中刪除了此訊號量,返回eidrm;

③程序捕捉到乙個信 號,並從訊號處理程式返回,返回eintr。(與訊息佇列的阻塞處理方式 很相似)

sem_***:訊號操作標誌,可能的選擇有兩種

ipc_nowait //對訊號的操作不能滿足時,semop()不會阻塞,並立即返回,同時設定錯誤資訊。

em_undo //程式結束時(不論正常或不正常),保證訊號值會被重設為semop()呼叫前值。

這樣做的目的在於避免程式在異常情況下結束時未將鎖定的資源解鎖,造成該資源永遠鎖定。

3 semctl()函式對乙個訊號量執行各種控制操作
標頭檔案:

#include #include #include 原型:

int semctl(int semid, int semnum, int cmd, /*可選引數*/);

semid:訊號集的識別碼,可以通過semget獲取。

semnu:指定訊號集中的哪個訊號(操作物件)

cmd:指定以下10種命令中的一種,在semid指定的訊號量集合上執行此命令。

ipc_stat 讀取乙個訊號量集的資料結構semid_ds,並將其儲存在semun中的buf引數中。

ipc_set 設定訊號量集的資料結構semid_ds中的元素ipc_perm,其值取自semun中的buf引數。

ipc_rmid 將訊號量集從記憶體中刪除。

getall 用於讀取訊號量集中的所有訊號量的值。

getncnt 返回正在等待資源的程序數目。

getpid 返回最後乙個執行semop操作的程序的pid。

getval 返回訊號量集中的乙個單個的訊號量的值。

getzcnt 返回這在等待完全空閒的資源的程序數目。

setall 設定訊號量集中的所有的訊號量的值。

setval 設定訊號量集中的乙個單獨的訊號量的值。

可選引數:取決於cmd若設定則為union semun型別

例項

head.h

#ifndef _mysem_h_

#define _mysem_h_

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define path "."

#define bufmax 1024

union semun

;extern

intsem_init

(int semid,

int id,

int vale)

;//訊號量集合初始化

extern

intsems_create

(int nums)

;//建立nums個訊號量的集合

extern

intsems_destroy

(int semid)

;//釋放訊號量集

extern

intsem_p

(int semid,

int id)

;//分配

extern

intsem_v

(int semid,

int id)

;//釋放

#endif

sem.c

#include

"./head.h"

intsem_init

(int semid,

int id,

int vale)

//訊號量集合初始化

return0;

}int

sems_create

(int nums)

//建立nums個訊號量的集合

int semid=

semget

(key,nums,ipc_creat|

0666);

//建立訊號量

if(semid<0)

return semid;

}int

_semop

(int semid,

int id,

int vale)

return0;

}int

sems_destroy

(int semid)

//釋放訊號量集

return0;

}int

sem_p

(int semid,

int id)

//分配

intsem_v

(int semid,

int id)

//釋放

main.c

#include

"./head.h"

intmain()

else

if(pid==0)

//子程序

}else

//父程序

wait

(null);

}sems_destroy

(semid)

;return0;

}

訊號量就是對資源的鎖定和釋放

linux 訊號量(程序間通訊)

將使用乙個程式來演示訊號量的使用,程式用pv操作控制訊號量,以操作臨界區,p操作讓訊號量減1,v操作讓訊號量加1,而pv操作之間的 即為臨界區關鍵 每次只能由乙個程序訪問。程式建立出乙個子程序,在兩個程序中分別有一段臨界區關鍵 實現的功能都是不斷的順序輸出0 9的字元。保證程序間同步 plain v...

linux 程序間通訊 訊號量

例項中首先使用fork 建立乙個子程序,在父程序呼叫kill 之前,在子程序中使用raise 向自身傳送sigstop訊號,是子程序暫停。接下來使用kill 向子程序傳送訊號 ngnsvr9 none home xionghailong example cat kill raise.c includ...

Linux 程序間通訊 訊號量

linux學習目錄 1 什麼是訊號量?在對於臨界區資源管理過程中,為了防止多個程式同時訪問乙個共享資源而引發的一系列問題。比如 死鎖。為了解決這種問題,巨人們就發明了訊號量。訊號量就是為了解決在乙個臨界區只有乙個程序訪問它,也就是說訊號量相當於交警,來協調程序對共享資源有序的訪問而不造成死鎖等行為。...