色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

信號(hào)量實(shí)現(xiàn)原理介紹

strongerHuang ? 來(lái)源:嵌入式藝術(shù) ? 2024-01-10 09:07 ? 次閱讀

轉(zhuǎn)自 |嵌入式藝術(shù) 除了原子操作,中斷屏蔽,自旋鎖以及自旋鎖的衍生鎖之外,在Linux內(nèi)核中還存在著一些其他同步互斥的手段。

下面我們來(lái)理解一下信號(hào)量,互斥體,完成量機(jī)制。

1、信號(hào)量介紹

信號(hào)量(Semaphore)是操作系統(tǒng)中最典型的用于同步和互斥的手段,信號(hào)量的值可以是0、1或者n。信號(hào)量與操作系統(tǒng)中的經(jīng)典概念PV操作對(duì)應(yīng)。 P(Produce):

將信號(hào)量S的值減1,即S=S-1;

如果S≥0,則該進(jìn)程繼續(xù)執(zhí)行;否則該進(jìn)程置為等待狀態(tài),排入等待隊(duì)列。

V(Vaporize):

將信號(hào)量S的值加1,即S=S+1;

如果S>0,喚醒隊(duì)列中等待信號(hào)量的進(jìn)程。

信號(hào)量核心思想: 信號(hào)量的操作,更適合去解決生產(chǎn)者和消費(fèi)者的問(wèn)題,比如:我做出來(lái)一個(gè)餅,你才能吃一個(gè)餅;如果我沒(méi)做出來(lái),你就先釋放CPU去忙其他的事情。

2、信號(hào)量的API

struct semaphore sem; // 定義信號(hào)量

void sema_init(struct semaphore *sem, int val); // 初始化信號(hào)量,并設(shè)置信號(hào)量sem的值為val。

void down(struct semaphore * sem); // 獲得信號(hào)量sem,它會(huì)導(dǎo)致睡眠,因此不能在中斷上下文中使用。
int down_interruptible(struct semaphore * sem); // 該函數(shù)功能與down類(lèi)似,不同之處為,因?yàn)閐own()進(jìn)入睡眠狀態(tài)的進(jìn)程不能被信號(hào)打斷,但因?yàn)閐own_interruptible()進(jìn)入睡眠狀態(tài)的進(jìn)程能被信號(hào)打斷,信號(hào)也會(huì)導(dǎo)致該函數(shù)返回,這時(shí)候函數(shù)的返回值非0
int down_trylock(struct semaphore * sem); // 嘗試獲得信號(hào)量sem,如果能夠立刻獲得,它就獲得該信號(hào)量并返回0,否則,返回非0值。它不會(huì)導(dǎo)致調(diào)用者睡眠,可以在中斷上下文中使用。

void up(struct semaphore * sem); // 釋放信號(hào)量,喚醒等待者。

由于新的Linux內(nèi)核傾向于直接使用mutex作為互斥手段,信號(hào)量用作互斥不再被推薦使用。 信號(hào)量也可以用于同步,一個(gè)進(jìn)程A執(zhí)行down()等待信號(hào)量,另外一個(gè)進(jìn)程B執(zhí)行up()釋放信號(hào)量,這樣進(jìn)程A就同步地等待了進(jìn)程B。

3、API實(shí)現(xiàn)

3.1 semaphore

struct semaphore {
raw_spinlock_t lock;
unsigned int count;
struct list_head wait_list;
};

結(jié)構(gòu)體名稱(chēng):semaphore

文件位置:include/linux/semaphore.h

主要作用:用于定義一個(gè)信號(hào)量。

raw_spinlock_t:信號(hào)量結(jié)構(gòu)體也使用了自旋鎖,避免互斥。

count:表示信號(hào)量的計(jì)數(shù)器,表示資源的數(shù)量

struct list_head wait_list: 這是一個(gè)鏈表頭,用于管理等待信號(hào)量的線(xiàn)程。當(dāng)信號(hào)量的 count 等于0,即沒(méi)有可用資源時(shí),等待信號(hào)量的線(xiàn)程會(huì)被加入到這個(gè)鏈表中,以便在資源可用時(shí)進(jìn)行喚醒。

3.2 sema_init

static inline void sema_init(struct semaphore *sem, int val)
{
static struct lock_class_key __key;
*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
}

#define __SEMAPHORE_INITIALIZER(name, n)
{
.lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock),
.count = n,
.wait_list = LIST_HEAD_INIT((name).wait_list),
}

#define LIST_HEAD_INIT(name) { &(name), &(name) }

函數(shù)名稱(chēng):sema_init

文件位置:include/linux/semaphore.h

主要作用:初始化信號(hào)量,并設(shè)置信號(hào)量sem的值為val。

實(shí)現(xiàn)流程

使用__SEMAPHORE_INITIALIZER宏定義來(lái)初始化信號(hào)量

使用__RAW_SPIN_LOCK_UNLOCKED宏定義來(lái)初始化自旋鎖

直接將val賦值給信號(hào)量的值count

使用LIST_HEAD_INIT來(lái)初始化一個(gè)鏈表


#defineLIST_HEAD_INIT(name){&(name),&(name)}

該宏接受一個(gè)參數(shù) name,并返回一個(gè)結(jié)構(gòu)體對(duì)象。這個(gè)對(duì)象有兩個(gè)成員 next 和 prev,分別指向 name 本身。

這樣,當(dāng)我們使用該宏來(lái)初始化鏈表頭節(jié)點(diǎn)時(shí),會(huì)得到一個(gè)擁有 next 和 prev 成員的結(jié)構(gòu)體對(duì)象。其中 next 和 prev 成員都指向該結(jié)構(gòu)體對(duì)象本身。

這種初始化方式可以用于創(chuàng)建一個(gè)空的雙向鏈表,因?yàn)樵诔跏紶顟B(tài)下,鏈表頭節(jié)點(diǎn)的 next 和 prev 指針都指向自身,表示鏈表為空。

3.3 down

/**

down - acquire the semaphore
@sem: the semaphore to be acquired

Acquires the semaphore. If no more tasks are allowed to acquire the
semaphore, calling this function will put the task to sleep until the
semaphore is released.

Use of this function is deprecated, please use down_interruptible() or
down_killable() instead.
*/
void down(struct semaphore *sem)
{
unsigned long flags;

raw_spin_lock_irqsave(&sem->lock, flags);
if (likely(sem->count > 0))
sem->count--;
else
__down(sem);
raw_spin_unlock_irqrestore(&sem->lock, flags);
}
EXPORT_SYMBOL(down);

static noinline void __sched __down(struct semaphore *sem)
{
__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}

/*

Because this function is inlined, the 'state' parameter will be
constant, and thus optimised away by the compiler. Likewise the
'timeout' parameter for the cases without timeouts.
*/
static inline int __sched __down_common(struct semaphore *sem, long state,
long timeout)
{
struct semaphore_waiter waiter;

list_add_tail(&waiter.list, &sem->wait_list);
waiter.task = current;
waiter.up = false;

for (;;) {
if (signal_pending_state(state, current))
goto interrupted;
if (unlikely(timeout <= 0))
goto timed_out;
__set_current_state(state);
raw_spin_unlock_irq(&sem->lock);
timeout = schedule_timeout(timeout);
raw_spin_lock_irq(&sem->lock);
if (waiter.up)
return 0;
}

timed_out:
list_del(&waiter.list);
return -ETIME;

interrupted:
list_del(&waiter.list);
return -EINTR;
}


函數(shù)名稱(chēng):down

文件位置:kernel/locking/semaphore.c

主要作用:獲取信號(hào)量,如果信號(hào)量的值大于0,則消耗一個(gè);如果不存在,則讓線(xiàn)程進(jìn)入休眠狀態(tài)并等待信號(hào)量被釋放。

函數(shù)調(diào)用流程


down(kernel/locking/semaphore.c)
|--> raw_spin_lock_irqsave // 獲取鎖,并保存中斷信息
||-> sem->count--; // 如果sem->count信號(hào)量存在,則消耗一個(gè)
|-> __down // 如果sem->count信號(hào)量不存在,則進(jìn)入休眠狀態(tài)
|--> __down_common
|--> list_add_tail // 將當(dāng)前線(xiàn)程添加到信號(hào)量的等待鏈表中,表示當(dāng)前線(xiàn)程正在等待信號(hào)量。
|--> __set_current_state// 設(shè)置線(xiàn)程為休眠狀態(tài)
|--> raw_spin_unlock_irq// 釋放自旋鎖,讓其他線(xiàn)程可用
|--> schedule_timeout // 讓線(xiàn)程進(jìn)入睡眠狀態(tài),等待信號(hào)量釋放或超時(shí)。
|--> raw_spin_lock_irq // 重新獲取自旋鎖,繼續(xù)執(zhí)行后續(xù)操作
|--> raw_spin_unlock_irqrestore // 釋放鎖,并恢復(fù)中斷信息

實(shí)現(xiàn)流程

獲取信號(hào)量時(shí),先使用raw_spin_lock_irqsave和raw_spin_unlock_irqrestore將信號(hào)量的操作包裹起來(lái),避免競(jìng)態(tài)發(fā)生。

然后對(duì)sem->count判斷,如果信號(hào)量大于0,就消耗一個(gè),否則的話(huà),將當(dāng)前線(xiàn)程設(shè)置為休眠態(tài)

調(diào)用__down_common接口,默認(rèn)將當(dāng)前線(xiàn)程設(shè)置為T(mén)ASK_UNINTERRUPTIBLE中斷不可打斷狀態(tài),并設(shè)置最大超時(shí)時(shí)間MAX_SCHEDULE_TIMEOUT

struct semaphore_waiter waiter:創(chuàng)建waiter結(jié)構(gòu)體,表示當(dāng)前線(xiàn)程的狀態(tài)

調(diào)用__set_current_state接口,設(shè)置當(dāng)前線(xiàn)程的狀態(tài)信息,即TASK_UNINTERRUPTIBLE

調(diào)用schedule_timeout,讓該線(xiàn)程讓出CPU,進(jìn)入休眠態(tài),并且在前面加上raw_spin_unlock_irq保證其他線(xiàn)程可以正常使用信號(hào)量。

當(dāng)線(xiàn)程時(shí)間片到時(shí),獲取CPU,并調(diào)用raw_spin_lock_irq,獲取鎖,來(lái)防止競(jìng)態(tài)發(fā)生。

3.4 up

/**

up - release the semaphore
@sem: the semaphore to release
Release the semaphore. Unlike mutexes, up() may be called from any
context and even by tasks which have never called down().
*/
void up(struct semaphore *sem)
{
unsigned long flags;

raw_spin_lock_irqsave(&sem->lock, flags);
if (likely(list_empty(&sem->wait_list)))
sem->count++;
else
__up(sem);
raw_spin_unlock_irqrestore(&sem->lock, flags);
}
EXPORT_SYMBOL(up);

static noinline void __sched __up(struct semaphore *sem)
{
struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
struct semaphore_waiter, list);
list_del(&waiter->list);
waiter->up = true;
wake_up_process(waiter->task);
}


函數(shù)名稱(chēng):up

文件位置:kernel/locking/semaphore.c

主要作用:獲取信號(hào)量,如果信號(hào)量的值大于0,則消耗一個(gè);如果不存在,則讓線(xiàn)程進(jìn)入休眠狀態(tài)并等待信號(hào)量被釋放。

實(shí)現(xiàn)流程

相信分析完down后,up也變得很簡(jiǎn)單

釋放信號(hào)量時(shí),先使用raw_spin_lock_irqsave和raw_spin_unlock_irqrestore將信號(hào)量的操作包裹起來(lái),避免競(jìng)態(tài)發(fā)生。

然后對(duì)sem->wait_list判斷,如果其為空,說(shuō)明沒(méi)有等待的線(xiàn)程,直接將sem->count自增,如果有等待的線(xiàn)程,則喚醒下一個(gè)線(xiàn)程。

調(diào)用wake_up_process來(lái)喚醒線(xiàn)程

4、總結(jié)

信號(hào)量較為簡(jiǎn)單,一般常用來(lái)解決生產(chǎn)者和消費(fèi)者的問(wèn)題,其主要還是通過(guò)自旋鎖來(lái)實(shí)現(xiàn)互斥的作用,通過(guò)鏈表來(lái)管理等待隊(duì)列的線(xiàn)程信息,通過(guò)變量來(lái)代表資源的數(shù)量。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 計(jì)數(shù)器
    +關(guān)注

    關(guān)注

    32

    文章

    2256

    瀏覽量

    94477
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21644
  • 信號(hào)量
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    8331
  • 自旋鎖
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    1580

原文標(biāo)題:信號(hào)量實(shí)現(xiàn)原理

文章出處:【微信號(hào):strongerHuang,微信公眾號(hào):strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    FreeRTOS信號(hào)量使用教程

    信號(hào)量是操作系統(tǒng)中重要的一部分,信號(hào)量一般用來(lái)進(jìn)行資源管理和任務(wù)同步, FreeRTOS中信號(hào)量又分為二值信號(hào)量、 計(jì)數(shù)型信號(hào)量、互斥
    的頭像 發(fā)表于 12-19 09:22 ?3199次閱讀
    FreeRTOS<b class='flag-5'>信號(hào)量</b>使用教程

    信號(hào)量是什么?信號(hào)量怎么運(yùn)作

    信號(hào)量信號(hào)量簡(jiǎn)介二值信號(hào)量計(jì)數(shù)信號(hào)量應(yīng)用場(chǎng)景二值信號(hào)量怎么運(yùn)作計(jì)數(shù)信號(hào)量怎么運(yùn)作
    發(fā)表于 01-05 08:09

    如何用VxWorks的信號(hào)量機(jī)制實(shí)現(xiàn)任務(wù)同步

    如何用VxWorks的信號(hào)量機(jī)制實(shí)現(xiàn)任務(wù)同步
    發(fā)表于 03-29 12:25 ?16次下載

    簡(jiǎn)單介紹信號(hào)信號(hào)量

    信號(hào)量實(shí)際上是一種約定機(jī)制,在多任務(wù)內(nèi)核中普遍使用。信號(hào)量用于:控制共享資源的使用權(quán)(滿(mǎn)足互斥條件)標(biāo)志某事件的發(fā)生使兩個(gè)任務(wù)的行為同步。
    的頭像 發(fā)表于 05-25 10:14 ?9640次閱讀
    簡(jiǎn)單<b class='flag-5'>介紹信號(hào)</b>與<b class='flag-5'>信號(hào)量</b>

    你了解Linux 各類(lèi)信號(hào)量

    內(nèi)核信號(hào)量與用戶(hù)信號(hào)量,用戶(hù)信號(hào)量分為POXIS信號(hào)量和SYSTEMV信號(hào)量,POXIS信號(hào)量
    發(fā)表于 05-04 17:19 ?2515次閱讀
    你了解Linux 各類(lèi)<b class='flag-5'>信號(hào)量</b>?

    uCOS信號(hào)量源碼的詳細(xì)資料分析

    本文檔的主要內(nèi)容詳細(xì)介紹的是uCOS信號(hào)量源碼的詳細(xì)資料分析。 信號(hào)量相關(guān)的函數(shù) 創(chuàng)建一個(gè)信號(hào)量,參數(shù)是信號(hào)量的初始值,創(chuàng)建成功返回值是
    發(fā)表于 06-17 17:38 ?7次下載
    uCOS<b class='flag-5'>信號(hào)量</b>源碼的詳細(xì)資料分析

    詳解互斥信號(hào)量的概念和運(yùn)行

    1 、互 斥 信 號(hào) 1.1 互斥信號(hào)量的概念及其作用 互斥信號(hào)量的主要作用是對(duì)資源實(shí)現(xiàn)互斥訪(fǎng)問(wèn),使用二值信號(hào)量也可以
    的頭像 發(fā)表于 10-22 11:57 ?1.2w次閱讀
    詳解互斥<b class='flag-5'>信號(hào)量</b>的概念和運(yùn)行

    Linux信號(hào)量(2):POSIX 信號(hào)量

    上一章,講述了 SYSTEM V 信號(hào)量,主要運(yùn)行于進(jìn)程之間,本章主要介紹 POSIX 信號(hào)量:有名信號(hào)量、無(wú)名信號(hào)量。 POSIX
    的頭像 發(fā)表于 10-29 17:34 ?707次閱讀

    LINUX內(nèi)核的信號(hào)量設(shè)計(jì)與實(shí)現(xiàn)

    控制路徑可以睡眠。我們從 LINUX內(nèi)核信號(hào)量最直觀(guān)的設(shè)計(jì)/實(shí)現(xiàn)出發(fā),通過(guò)一步步改進(jìn),揭示在x86平臺(tái)上完整的信號(hào)量設(shè)計(jì)/實(shí)現(xiàn),然后探討在不同平臺(tái)上通用的
    發(fā)表于 01-14 16:55 ?18次下載

    LINUX內(nèi)核的信號(hào)量設(shè)計(jì)與實(shí)現(xiàn)

    控制路徑可以睡眠。我們從 LINUX內(nèi)核信號(hào)量最直觀(guān)的設(shè)計(jì)/實(shí)現(xiàn)出發(fā),通過(guò)一步步改進(jìn),揭示在x86平臺(tái)上完整的信號(hào)量設(shè)計(jì)/實(shí)現(xiàn),然后探討在不同平臺(tái)上通用的
    發(fā)表于 01-14 16:55 ?5次下載

    FreeRTOS的二值信號(hào)量

    FreeRTOS中的信號(hào)量是一種任務(wù)間通信的方式,信號(hào)量包括:二值信號(hào)量、互斥信號(hào)量、計(jì)數(shù)信號(hào)量,本次實(shí)驗(yàn)只使用二值
    的頭像 發(fā)表于 02-10 15:07 ?1501次閱讀

    Free RTOS的計(jì)數(shù)型信號(hào)量

    上篇講解了二值信號(hào)量,二值信號(hào)量只能判斷有無(wú),而不能確定事件發(fā)生的次數(shù),因此我們?yōu)榱舜_定事件的次數(shù)引入了計(jì)數(shù)型信號(hào)量
    的頭像 發(fā)表于 02-10 15:29 ?1023次閱讀
    Free RTOS的計(jì)數(shù)型<b class='flag-5'>信號(hào)量</b>

    使用Linux信號(hào)量實(shí)現(xiàn)互斥點(diǎn)燈

    信號(hào)量常用于控制對(duì)共享資源的訪(fǎng)問(wèn),有計(jì)數(shù)型信號(hào)量和二值信號(hào)量之分。初始化時(shí)信號(hào)量值大于1的,就是計(jì)數(shù)型信號(hào)量,計(jì)數(shù)型
    的頭像 發(fā)表于 04-13 15:12 ?803次閱讀
    使用Linux<b class='flag-5'>信號(hào)量</b><b class='flag-5'>實(shí)現(xiàn)</b>互斥點(diǎn)燈

    FreeRTOS四種信號(hào)量詳細(xì)介紹

    1、二值信號(hào)量 二值信號(hào)量通常用于互斥訪(fǎng)問(wèn)或同步,二值信號(hào)量和互斥信號(hào)量非常類(lèi)似,但是還是有一些細(xì)微的差別,互斥信號(hào)量擁有優(yōu)先級(jí)繼承機(jī)制,二
    的頭像 發(fā)表于 07-06 17:14 ?2590次閱讀

    Semaphore信號(hào)量概念及其介紹

    信號(hào)量即Semaphore。信號(hào)量主要用于控制和保護(hù)任務(wù)對(duì)特定資源的訪(fǎng)問(wèn)。
    的頭像 發(fā)表于 07-25 15:40 ?1728次閱讀
    Semaphore<b class='flag-5'>信號(hào)量</b>概念及其<b class='flag-5'>介紹</b>
    主站蜘蛛池模板: 亚洲免费在线视频| 国产又粗又猛又爽又黄的免费视频| 男女床上黄色| 69精品人妻一区二区三区蜜桃| 久拍国产在线观看| 中国老太性色xxxxxhd| 看电影就来5566先锋av| 最新亚洲中文字幕在线观看| 美女搜查官被高难度黑人在线播放| 2020国产欧洲精品视频| 男女啪啪久久精品亚洲A| caoporn 在线视频| 青青草国产偷拍在线av| 超碰视频97av| 天天影视色欲 影视| 国产欧美无码亚洲毛片| 亚洲精品国产乱码AV在线观看| 精品国产品国语在线不卡| 亚洲精品一区二区在线看片| 久久观看视频| 91亚洲精品| 日本中文一区| 国产九九九九九九九A片| 亚洲国产中文字幕在线视频| 久久精品国产亚洲AV妓女不卡| 13一18TV处流血TV| 欧美无码专区| 国产激情一级毛片久久久| 亚洲AV午夜精品麻豆AV| 久久成人国产精品一区二区| 97免费观看视频| 人人啪日日观看在线| 国产精品一区二区AV97| 亚洲无人区码二码三码区别图| 萝莉御姐被吸奶| 不用播放器的黄| 新图解av吧| 久久婷五月综合色啪首页| MD传媒在线观看佳片| 午夜国产福利| 在线日本v二区不卡|