Linux 程序間通訊 訊號量詳解及程式設計例項

2021-07-15 22:48:48 字數 4222 閱讀 2535

前面一篇文章執行緒同步之訊號量同步 講的是執行緒之間的訊號量,這篇講的更加具有通用性,能夠實現程序之間的同步。

它是乙個特殊變數,只允許對它進行等待和傳送訊號這兩種操作。

[cpp]view plain

copy

print?

semaphore sem_id = 1;  

loop  

linux系統中的訊號量介面經過了精心設計,提供了比通常所需更多的機制。所有的linux訊號量函式都是針對成組的通用訊號量進行操作,而不只是針對乙個二進位制訊號量。但是在絕大多數情況下,使用乙個單個訊號量就足夠了,所以在這裡只討論單個訊號量的使用。

用於建立乙個新的訊號量或者是取得乙個已有的訊號量的鍵。

所需包含的標頭檔案:

[cpp]view plain

copy

print?

#include 

它通常依賴於另兩個標頭檔案:

[cpp]view plain

copy

print?

#include 

#include 

一般情況下,這

兩個標頭檔案都會被它自動包含。

功能描述

函式原型:int semget(key_t key,int nsems,int sem***);

功能描述

獲取與某個鍵關聯的訊號量集標識。訊號量集被建立的情況有兩種:

1.如果鍵的值是ipc_private。

2.或者鍵的值不是ipc_private,並且鍵所對應的訊號量集不存在,同時標誌中指定ipc_creat。

當呼叫semget建立乙個訊號量時,他的相應的semid_ds結構被初始化。ipc_perm中各個量被設定為相應

值:sem_nsems被設定為nsems所示的值;

sem_otime被設定為0;

sem_ctime被設定為當前時間

引數解釋

key:所建立或開啟訊號量集的鍵值。需要是唯一的非零整數。

nsems:建立的訊號量集中的訊號量的個數,該引數只在建立訊號量集時有效。幾乎總是取值為1.

flag:呼叫函式的操作型別,也可用於設定訊號量集的訪問許可權,兩者通過or表示

返回值說明:

如果成功,則返回訊號量集的ipc識別符號(乙個正數)。

如果失敗,則返回-1,errno被設定成以下的某個值

eacces:沒有訪問該訊號量集的許可權

eexist:訊號量集已經存在,無法建立

einval:引數nsems的值小於0或者大於該訊號量集的限制;或者是該key關聯的訊號量集已存在,並且nsems

大於該訊號量集的訊號量數

enoent:訊號量集不存在,同時沒有使用ipc_creat

enomem :沒有足夠的記憶體建立新的訊號量集

enospc:超出系統限制

用於改變訊號量的值。

[cpp]view plain

copy

print?

#include 

intsemop( 

intsemid, 

struct

sembuf semoparray, 

size_t

nops );   

引數解釋:

引數semid是乙個通過semget函式返回的乙個訊號量識別符號

引數nops標明了引數semoparray所指向陣列中的元素個數

引數semoparray是乙個struct sembuf結構型別的陣列指標,

結構sembuf來說明所要執行的操作,其定義如下:

[cpp]view plain

copy

print?

struct

sembuf  

在sembuf結構中,

sem_num是相對應的訊號量集中的某乙個資源,所以其值是乙個從0到相應的訊號量集的資源總數(ipc_perm.sem_nsems)之間的整數。除非使用一組訊號了,否則它的取值一般為0.

sem_op的值是乙個整數,是訊號量在一次操作中需要改變的數值(可以是非1的數值)。通常只會用到兩個值:1----p操作,-1---v操作。

sem_***說明函式semop的行為。通常被設定為sem_undo。它將使得作業系統跟著當前程序對這個訊號量的修改情況,如果這個程序在沒有釋放該訊號量的情況下終止,作業系統將自動釋放該程序持有的訊號量。

注意:semop呼叫的一切動作都是一次性完成的,這是為了避免出現因使用多個訊號量而可能發生的競爭現象。

原型:

[cpp]view plain

copy

print?

intsemctl(

intsemid,

intsemnum,

intcmd,

union

semun);  

返回值:

如果成功,則為乙個正數。

如果失敗,則為-1:

errno=eaccess(許可權不夠)

efault(arg指向的位址無效)

eidrm(訊號量集已經刪除)

einval(訊號量集不存在,或者semid無效)

eperm(euid沒有cmd的權利)

erange(訊號量值超出範圍) 

引數解釋:

sem_id是由semget返回的訊號量識別符號。

sem_num與前面乙個函式相同。

***:表示將要採取的動作。最常用的兩個值如下:

semun聯合結構的定義:

[cpp]view plain

copy

print?

semun是在linux/sem.h中定義的:  

/*arg for semctl systemcalls.*/

union

semun;  

//函式宣告

//函式:設定訊號量的值

static

intset_semvalue(

void

);  

//函式:刪除訊號量

static

void

del_semvalue(

void

);  

//函式:訊號量p操作

static

intsemaphore_p(

void

);  

//函式:訊號量v操作

static

intsemaphore_v(

void

);  

static

intsem_id;

//訊號量id

intmain(

intargc,

char

*argv)  

op_char = 'x'

;//對程序進行標記

sleep(5);  

}  //迴圈:訪問臨界區

for(i = 0;i 

printf("\n %d - finished \n"

,getpid());  

if(argc > 1)  

}  //函式:設定訊號量的值

static

intset_semvalue(

void

)    

//函式:刪除訊號量

static

void

del_semvalue(

void

)    

//函式:訊號量p操作:對訊號量進行減一操作

static

intsemaphore_p(

void

)    

return

1;  

}  //函式:訊號量v操作:對訊號量進行加一操作

static

intsemaphore_v(

void

)    

return

1;  

}  

執行結果:

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