精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux信號量(2):POSIX 信號量

電子設計 ? 來源:電子設計 ? 作者:電子設計 ? 2020-10-29 17:34 ? 次閱讀

上一章,講述了 SYSTEM V 信號量,主要運行于進程之間,本章主要介紹 POSIX 信號量:有名信號量、無名信號量。

POSIX 信號量

POSIX 信號量進程是 3 種 IPC(Inter-Process Communication) 機制之一,3 種 IPC 機制源于 POSIX.1 的實時擴展。Single UNIX Specification 將 3 種機制(消息隊列,信號量和共享存儲)置于可選部分中。在 SUSv4 之前,POSIX 信號量接口已經被包含在信號量選項中。在 SUSv4 中,這些接口被移至了基本規范,而消息隊列和共享存儲接口依然是可選的。

POSIX 信號量接口意在解決 XSI 信號量接口的幾個缺陷。

相比于 XSI 接口,POSIX 信號量接口考慮了更高性能的實現。

POSIX 信號量使用更簡單:沒有信號量集,在熟悉的文件系統操作后一些接口被模式化了。盡管沒有要求一定要在文件系統中實現,但是一些系統的確是這么實現的。

POSIX 信號量在刪除時表現更完美。回憶一下,當一個 XSI 信號量被刪除時,使用這個信號量標識符的操作會失敗,并將 errno 設置成 EIDRM。使用 POSIX 信號量時,操作能繼續正常工作直到該信號量的最后一次引用被釋放。

分類

POSIX 信號量是一個 sem_t 類型的變量,但 POSIX 有兩種信號量的實現機制:無名信號量和命名信號量。無名信號量只可以在共享內存的情況下,比如實現進程中各個線程之間的互斥和同步,因此無名信號量也被稱作基于內存的信號量;命名信號量通常用于不共享內存的情況下,比如進程間通信。

同時,在創建信號量時,根據信號量取值的不同,POSIX 信號量還可以分為:

二值信號量:信號量的值只有 0 和 1,這和互斥量很類似,若資源被鎖住,信號量的值為 0,若資源可用,則信號量的值為 1;

計數信號量:信號量的值在 0 到一個大于 1 的限制值之間,該計數表示可用的資源的個數。

區別

有名信號量和無名信號量的差異在于創建和銷毀的形式上,但是其他工作一樣。

無名信號量只能存在于內存中,要求使用信號量的進程必須能訪問信號量所在的這一塊內存,所以無名信號量只能應用在同一進程內的線程之間(共享進程的內存),或者不同進程中已經映射相同內存內容到它們的地址空間中的線程(即信號量所在內存被通信的進程共享)。意思是說無名信號量只能通過共享內存訪問。

相反,有名信號量可以通過名字訪問,因此可以被任何知道它們名字的進程中的線程使用。

單個進程中使用 POSIX 信號量時,無名信號量更簡單。多個進程間使用 POSIX 信號量時,有名信號量更簡單。

聯系

無論是有名信號量還是無名信號量,都可以通過以下函數進行信號量值操作。

wait(P)

wait 為信號量值減一操作,總共有三個函數,函數原型如下:


#include

intsem_wait(sem_t*sem);

intsem_trywait(sem_t*sem);

intsem_timedwait(sem_t*sem,conststructtimespec*abs_timeout);

Linkwith-pthread. 這一句表示gcc編譯時,要加-pthread.


返回值:
若成功,返回0;若出錯,返回 -1

sem_wait 的作用是,若 sem 小于 0 ,則線程阻塞于信號量 sem ,直到 sem 大于 0 ;否則信號量值減 1。

sem_trywait 作用與 sem_wait 相同,只是此函數不阻塞線程,如果 sem 小于 0,直接返回一個錯誤(錯誤設置為 EAGAIN )。

sem_timedwait 作用也與 sem_wait 相同,第二個參數表示阻塞時間,如果 sem 小于 0 ,則會阻塞,參數指定阻塞時間長度。abs_timeout 指向一個結構體,這個結構體由從 1970-01-01 00:00:00 +0000 (UTC) 開始的秒數和納秒數構成。

結構體定義如下:

structtimespec{
time_ttv_sec;/*Seconds*/
longtv_nsec;/*Nanoseconds[0..999999999]*/
};

如果指定的阻塞時間到了,但是 sem 仍然小于 0 ,則會返回一個錯誤 (錯誤設置為 ETIMEDOUT )。

post(V)

post 為信號量值加一操作,函數原型如下:


#include
intsem_post(sem_t*sem);
Linkwith-pthread.
返回值:
若成功,返回0;若出錯,返回 -1

無名信號量

接口函數

信號量的函數都以 sem_ 開頭,線程中使用的基本信號函數有 4 個,他們都聲明在頭文件 semaphore.h 中,該頭文件定義了用于信號量操作的 sem_t 類型:

sem_init

該函數用于創建信號量,原型如下:


intsem_init(sem_t*sem,intpshared,unsignedintvalue);

功能:該函數初始化由 sem 指向的信號對象,設置它的共享選項,并給它一個初始的整數值。pshared 控制信號量的類型,如果其值為 0,就表示信號量是當前進程的局部信號量,否則信號量就可以在多個進程間共享,value 為 sem 的初始值。返回值:該函數調用成功返回 0,失敗返回 -1。

sem_destroy

該函數用于對用完的信號量進行清理,其原型如下:


intsem_destroy(sem_t*sem);

返回值:

成功返回 0,失敗返回 -1。

sem_getvalue 函數

該函數返回當前信號量的值,通過 restrict 輸出參數返回。如果當前信號量已經上鎖(即同步對象不可用),那么返回值為 0,或為負數,其絕對值就是等待該信號量解鎖的線程數。


intsem_getvalue(sem_t*restrict,int*restrict);

使用實例

【實例 1】:

#include

#include

#include

#include

#include

#include

#include

#include

sem_tsem;

#definehandle_error(msg)do{/
perror(msg);/
exit(EXIT_FAILURE);/
}while(0)
staticvoidhandler(intsig){
write(STDOUT_FILENO,"sem_post()fromhandler/n",24);
if(sem_post(&sem)==-1)
{
write(STDERR_FILENO,"sem_post()failed/n",18);
_exit(EXIT_FAILURE);
}}
intmain(intargc,char*argv[]){
ints;
structtimespects;
structsigactionsa;

if(argc!=3)
{
fprintf(stderr,"Usage:%s/n",argv[0]);
exit(EXIT_FAILURE);
}

if(sem_init(&sem,0,0)==-1)
handle_error("sem_init");

/*EstablishSIGALRMhandler;setalarmtimerusingargv[1]*/
sa.sa_handler=handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGALRM,&sa,NULL)==-1)
handle_error("sigaction");

alarm(atoi(argv[1]));

/*Calculaterelativeintervalascurrenttimeplus
numberofsecondsgivenargv[2]*/

if(clock_gettime(CLOCK_REALTIME,&ts)==-1)
handle_error("clock_gettime");

ts.tv_sec+=atoi(argv[2]);

printf("main()abouttocallsem_timedwait()/n");
while((s=sem_timedwait(&sem,&ts))==-1&&errno==EINTR)
continue;/*Restartifinterruptedbyhandler*/

/*Checkwhathappened*/
if(s==-1)
{
if(errno==ETIMEDOUT)
printf("sem_timedwait()timedout/n");
else
perror("sem_timedwait");
}
else
{
printf("sem_timedwait()succeeded/n");
}

exit((s==0)?EXIT_SUCCESS:EXIT_FAILURE);

}

【實例 2】:

#include

#include

#include

#include

#include

#include

#include

#include

sem_tsem;
void*func1(void*arg){
sem_wait(&sem);
int*running=(int*)arg;
printf("threadfunc1running:%d/n",*running);

pthread_exit(NULL);
}
void*func2(void*arg)
{
printf("threadfunc2running./n");
sem_post(&sem);

pthread_exit(NULL);
}
intmain(void)
{
inta=3;
sem_init(&sem,0,0);
pthread_tthread_id[2];

pthread_create(&thread_id[0],NULL,func1,(void*)&a);
printf("mainthreadrunning./n");
sleep(10);
pthread_create(&thread_id[1],NULL,func2,(void*)&a);
printf("mainthreadstillrunning./n");
pthread_join(thread_id[0],NULL);
pthread_join(thread_id[1],NULL);
sem_destroy(&sem);

return0;
}

有名信號量

有時候也叫命名信號量,之所以稱為命名信號量,是因為它有一個名字、一個用戶 ID、一個組 ID 和權限。這些是提供給不共享內存的那些進程使用命名信號量的接口。命名信號量的名字是一個遵守路徑名構造規則的字符串。

接口函數

sem_open 函數

該函數用于創建或打開一個命名信號量,其原型如下:


sem_t*sem_open(constchar*name,intoflag);
sem_t*sem_open(constchar*name,intoflag,mode_tmode,unsignedintvalue);

參數

name 是一個標識信號量的字符串。

oflag 用來確定是創建信號量還是連接已有的信號量。oflag 的參數可以為 0,O_CREAT 或 O_EXCL:如果為 0,表示打開一個已存在的信號量;如果為 O_CREAT,表示如果信號量不存在就創建一個信號量,如果存在則打開被返回,此時 mode 和 value 都需要指定;如果為 O_CREAT|O_EXCL,表示如果信號量存在則返回錯誤。

mode 用于創建信號量時指定信號量的權限位,和 open 函數一樣,包括:S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH、S_IWOTH。

value 表示創建信號量時,信號量的初始值。

sem_close 函數

該函數用于關閉命名信號量:


intsem_close(sem_t*);

功能:單個程序可以用 sem_close 函數關閉命名信號量,但是這樣做并不能將信號量從系統中刪除,因為命名信號量在單個程序執行之外是具有持久性的。當進程調用 _exit、exit、exec 或從 main 返回時,進程打開的命名信號量同樣會被關閉。

sem_unlink 函數功能:sem_unlink 函數用于在所有進程關閉了命名信號量之后,將信號量從系統中刪除:


intsem_unlink(constchar*name);

信號量操作函數與無名信號量一樣。

使用實例

#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineSEM_NAME"/sem_name"
sem_t*p_sem;
void*testThread(void*ptr){
sem_wait(p_sem);
sleep(2);
pthread_exit(NULL);}
intmain(void){
inti=0;
pthread_tpid;
intsem_val=0;
p_sem=sem_open(SEM_NAME,O_CREAT,0555,5);

if(p_sem==NULL)
{
printf("sem_open%sfailed!/n",SEM_NAME);
sem_unlink(SEM_NAME);
return-1;
}

for(i=0;i

命名和無名信號量的持續性

命名信號量是隨內核持續的。當命名信號量創建后,即使當前沒有進程打開某個信號量,它的值依然保持,直到內核重新自舉或調用 sem_unlink()刪除該信號量。

無名信號量的持續性要根據信號量在內存中的位置確定:

如果無名信號量是在單個進程內部的數據空間中,即信號量只能在進程內部的各個線程間共享,那么信號量是隨進程的持續性,當進程終止時他也就消失了;

如果無名信號量位于不同進程的共享內存區,因此只要該共享內存區仍然存在,該信號量就會一直存在;所以此時無名信號量是隨內核的持續性。

信號量 - 互斥量 - 條件變量

很多時候信號量、互斥量和條件變量都可以在某種應用中使用,那這三者的差異有哪些呢?下面列出了這三者之間的差異:

互斥量必須由給它上鎖的線程解鎖;而信號量不需要由等待它的線程進行掛出,可以在其他進程進行掛出操作;

互斥量要么被鎖住,要么被解開,只有這兩種狀態;而信號量的值可以支持多個進程 / 線程成功的進行 wait 操作;

信號量的掛出操作總是被記住,因為信號量有一個計數值,掛出操作總會將該計數值加 1,然而當條件變量發送一個信號時,如果沒有線程等待在條件變量,那么該信號就會丟失。

審核編輯 黃昊宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11232

    瀏覽量

    208950
  • Posix
    +關注

    關注

    0

    文章

    36

    瀏覽量

    9488
  • 信號量
    +關注

    關注

    0

    文章

    53

    瀏覽量

    8315
收藏 人收藏

    評論

    相關推薦

    基于OpenHarmony標準系統的C++公共基礎類庫案例:Semaphore

    的公共資源變量; 創建5個線程,每個線程做5次for循環,for循環的內容是獲取無名信號量,并修改公共資源變量; (2)有名信號量使用方法 定義1個有名信號量,1個供有名
    發表于 08-14 16:38

    PLC對模擬信號的處理過程及方法 詳解版

    模擬信號是自動化過程控制系統中最基本的過程信號(壓力、溫度、流量等)輸入形式。系統中的過程信號通過變送器,將這些檢測信號轉換為統一的電壓、
    的頭像 發表于 07-30 16:31 ?345次閱讀
    PLC對模擬<b class='flag-5'>量</b><b class='flag-5'>信號</b>的處理過程及方法 詳解版

    模擬信號和開關信號的重要區別以及具體應用

    。 ? ? ??但是對于一些剛入門學習PLC和變頻器的師傅而言就不同了,對于開關信號和模擬信號非常容易弄混亂,甚至分不清楚哪些設備是開關
    的頭像 發表于 07-21 16:09 ?449次閱讀
    模擬<b class='flag-5'>量</b><b class='flag-5'>信號</b>和開關<b class='flag-5'>量</b><b class='flag-5'>信號</b>的重要區別以及具體應用

    sem信號量下semxx-&gt;parent.suspend_thread-&gt;next的值,應該執行take線程的被改變成了release線程,為什么?

    在使用信號量時,一個線程release一個線程take,在某些特定時候,take線程永遠不執行了,release線程確認一直有釋放,sem下面的Value一直在增加, 詳細追蹤,發現在take
    發表于 07-12 14:36

    4到20ma模擬信號怎么測?及原理介紹

    ? ? ? 4到20mA模擬信號是一種常見的工業信號,用于傳輸模擬數據。在工業自動化、過程控制等領域中,4到20mA信號被廣泛應用于傳感
    的頭像 發表于 06-23 08:38 ?4670次閱讀
    4到20ma模擬<b class='flag-5'>量</b><b class='flag-5'>信號</b>怎么測?及原理介紹

    4到20ma模擬信號怎么測

    4到20mA模擬信號是一種常見的工業信號,用于傳輸模擬數據。在工業自動化、過程控制等領域中,4到20mA信號被廣泛應用于傳感器、變送器等
    的頭像 發表于 06-20 11:37 ?1605次閱讀

    關于FreeRTOS互斥的用法求解

    對于串口發送,我們都普遍用中斷方式發送, 可是在配合互斥的時候會遇到些問題, 互斥的使用 必須在同一個任務中 占用和釋放, 我目前的做法是用二值信號量 在 發送中斷完成時釋放信號,
    發表于 04-24 08:03

    STM32F107+CubeMX+FreeRTOS+LWIP連接成功后,信號量無法使用怎么解決?

    各位大哥,遇到一個在FreeRTOS+LWIP使用信號量的問題。 項目工程是通過CubeMX生成的,使用FreeRTOS + LWIP。 簡化代碼,FreeRTOS初始化兩個任務,一個默認任務、一個
    發表于 04-19 07:33

    嵌入式實時操作系統——二值信號量

    當用戶需要使用停車資源時,它靠近屏障并按下請求按鈕,在信號量術語中,該行為被定義為信號等待(wait)操作。由于資源處于空閑狀態,故服務員抬起屏障并回答可以通過, 用戶隨即進入保護區域,然后屏障關閉。
    發表于 04-09 14:44 ?628次閱讀
    嵌入式實時操作系統——二值<b class='flag-5'>信號量</b>

    plc模擬輸出怎么接線 plc模擬輸出是什么信號

    PLC模擬輸出(PLC Analog Output)是指在PLC系統中,根據輸入信號的大小,通過模擬輸出模塊將數字信號轉換為模擬
    的頭像 發表于 02-05 14:46 ?5272次閱讀

    Linux內核中信號詳解

    ? 1 信號的角色 1.1 x86/64架構信號定義 1.2 ARM架構信號定義 1.3 RISC-V架構信號定義 1.4 信號的系統調用
    的頭像 發表于 01-13 09:40 ?1333次閱讀
    <b class='flag-5'>Linux</b>內核中<b class='flag-5'>信號</b>詳解

    信號量實現原理介紹

    除了原子操作,中斷屏蔽,自旋鎖以及自旋鎖的衍生鎖之外,在Linux內核中還存在著一些其他同步互斥的手段。
    的頭像 發表于 01-10 09:07 ?1110次閱讀

    請問PLC是如何讀取模擬信號的?

    PLC讀取模擬信號必須要有模擬輸入模塊,即常說的AI模塊。
    的頭像 發表于 01-02 09:35 ?762次閱讀
    請問PLC是如何讀取模擬<b class='flag-5'>量</b><b class='flag-5'>信號</b>的?

    PLC開關信號和模擬信號如何轉換?

    PLC開關信號和模擬信號的轉化問題也是PLC的經典應用問題。要說清楚PLC開關信號和模擬
    發表于 12-17 10:05 ?1643次閱讀
    PLC開關<b class='flag-5'>量</b><b class='flag-5'>信號</b>和模擬<b class='flag-5'>量</b><b class='flag-5'>信號</b>如何轉換?

    FreeRTOS信號量的使用與實例

    在嵌入式系統中,任務管理是一個重要的部分,它涉及到任務之間的通信和同步,信號量,隊列,互斥鎖和事件標志組等概念。本文將以 FreeRTOS 為例,詳細講解這些內容。
    的頭像 發表于 12-12 15:25 ?2399次閱讀