前面一篇文章執行緒同步之訊號量同步 講的是執行緒之間的訊號量,這篇講的更加具有通用性,能夠實現程序之間的同步。
它是乙個特殊變數,只允許對它進行等待和傳送訊號這兩種操作。
[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 什麼是訊號量?在對於臨界區資源管理過程中,為了防止多個程式同時訪問乙個共享資源而引發的一系列問題。比如 死鎖。為了解決這種問題,巨人們就發明了訊號量。訊號量就是為了解決在乙個臨界區只有乙個程序訪問它,也就是說訊號量相當於交警,來協調程序對共享資源有序的訪問而不造成死鎖等行為。...