#include
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem_init() 初始化乙個定位在 sem 的匿名信號量。value 引數指定訊號量的初始值。
pshared 引數指明訊號量是由程序內線程共享,還是由程序之間共享。
如果 pshared 的值為 0,那麼訊號量將被程序內的執行緒共享,並且應該放置在所有執行緒都可見的位址上(如全域性變數,或者堆上動態分配的變數)。
如果 pshared 是非零值,那麼訊號量將在程序之間共享,並且應該定位共享記憶體區域(見 shm_open、mmap和shmget)。(因為通過 fork 建立的孩子繼承其父親的記憶體對映,因此它也可以見到這個訊號量。所有可以訪問共享記憶體區域的程序都可以用 sem_post(3)、sem_wait(3) 等等操作訊號量。
初始化乙個已經初始的訊號量其結果未定義。
int sem_wait(sem_t * sem);
sem_wait函式也是乙個原子操作,它的作用是從訊號量的值減去乙個「1」,但它永遠會先等待該訊號量為乙個非零值才開始做減法。也就是說,如果你對乙個值為2的訊號量呼叫sem_wait(),執行緒將會繼續執行,這訊號量的值將減到1。如果對乙個值為0的訊號量呼叫sem_wait(),這個函式就 會地等待直到有其它執行緒增加了這個值使它不再是0為止。如果有兩個執行緒都在sem_wait()中等待同乙個訊號量變成非零值,那麼當它被第三個執行緒增加 乙個「1」時,等待執行緒中只有乙個能夠對訊號量做減法並繼續執行,另乙個還將處於等待狀態。所有的函式成功返回0,錯誤的話訊號量的值不改動,返回-1.errno設定來標識錯誤.
sem_trywait(sem_t *sem)是函式sem_wait的非阻塞版,它直接將訊號量sem減1,同時返回錯誤**。
int sem_post(sem_t *sem);
sem_post函式的作用是給訊號量的值加上乙個「1」,它是乙個「原子操作」---即同時對同乙個訊號量做加「1」操作的兩個執行緒是不會衝突的;而同 時對同乙個檔案進行讀、加和寫操作的兩個程式就有可能會引起衝突。訊號量的值永遠會正確地加乙個「2」--因為有兩個執行緒試圖改變它。 當有執行緒阻塞在這個訊號量上時,呼叫這個函式會使其中乙個執行緒不在阻塞,選擇機制是有執行緒的排程策略決定的。
sem_post() 成功時返回 0;錯誤時,訊號量的值沒有更改,-1 被返回,並設定 errno 來指明錯誤。
int sem_destroy(sem_t *sem);
sem_destroy() 銷毀由sem指向的匿名信號量。
只有通過sem_init初始化的訊號量才應該使用sem_destroy() 銷毀。
銷毀乙個有其它執行緒或程序當前阻塞(在sem_wait)的訊號量將導致未定義行為。
使用乙個已經銷毀的訊號量將導致未定義結果,除非這個訊號量已經使用sem_init重新初始化了。
sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
oflag引數可以是0、o_creat(建立乙個訊號燈)或o_creat|o_excl(如果沒有指定的訊號燈就建立),如果指定了o_creat,那麼第三個和第四個引數是需要的;其中mode引數指定許可權位,value引數指定訊號燈的初始值,通常用來指定共享資源的書面。該初始不能超過sem_value_max,這個常值必須低於為32767。二值訊號燈的初始值通常為1,計數訊號燈的初始值則往往大於1。
如果指定了o_creat(而沒有指定o_excl),那麼只有所需的訊號燈尚未存在時才初始化它。所需訊號燈已存在條件下指定o_creat不是乙個錯誤。該標誌的意思僅僅是「如果所需訊號燈尚未存在,那就建立並初始化它」。但是所需訊號燈等已存在條件下指定o_creat|o_excl卻是乙個錯誤。
int sem_close (sem_t *__sem)
關閉匿名信號量(即關閉fd),和sem_open對應。
int sem_unlink (__const char *__name)
remove named semaphore name.
int sem_getvalue(sem_t *sem, int *sval);
sem_getvalue() 把 sem 指向的訊號量當前值放置在 sval 指向的整數上。 如果有乙個或多個程序或執行緒當前正在使用 sem_wait(3) 等待訊號量。
注意:訊號量的值可能在 sem_getvalue() 返回時已經被更改。
/*thread.c*/
#include #include #includesem_t my_sem1;
sem_t my_sem2;
void thread_1(void)
pthread_exit(0);
}
void thread_2(void)
pthread_exit(0);
}
int main(void)
ret = sem_init(&my_sem2, 1, 1);
if(ret != 0)
ret = pthread_create(&id_1, null, (void *)thread_1, null);
if(ret != 0)
ret = pthread_create(&id_2, null, (void *)thread_2, null);
if(ret != 0)
/*等待執行緒結束*/
pthread_join(id_1, null);
pthread_join(id_2, null);
sem_destroy(&my_sem1);
sem_destroy(&my_sem2);
return 0;
}
linux核心態和使用者態的訊號量
在linux的核心態和使用者態都有訊號量,使用也不同,簡單記錄一下。1 核心訊號量,由核心控制路徑使用。核心訊號量是struct semaphore型別的物件,它在中定義 struct semaphore atomic t count int sleepers void sema init stru...
解決競態問題之訊號量
1 訊號量簡介 訊號量是同步的一種方式,linux 核心也提供了訊號量機制,訊號量常常用於控制對共享資源的訪問。舉乙個很常見的例子,某個停車場有 100個停車位,這 100 個停車位大家都可以用,對於大家來說這100 個停車位就是共享資源。假設現在這個停車場正常執行,你要把車停到這個這個停車場肯定要...
訊號量 二值訊號量
訊號量 二值訊號量 訊號量是作業系統的重要部分,訊號量一般用來進行資源管理和任務同步。freertos中訊號量分為二值訊號量 互斥訊號量 計數訊號量和遞迴互斥訊號量,應用場景各不同。二值訊號量通常用於互斥訪問或同步,二值訊號量和互斥訊號量非常相似,但互斥訊號量有優先順序,二值訊號量沒有。因此二值訊號...