日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信号量机制中的down和up函数

發(fā)布時間:2023/12/8 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信号量机制中的down和up函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)自:https://blog.csdn.net/fzubbsc/article/details/37737159

參考:

https://blog.csdn.net/liuxd3000/article/details/17913363

http://blog.chinaunix.net/uid-25845340-id-3017214.html?

https://blog.csdn.net/xiao229404041/article/details/7031776

查閱文件:

kernel\linux\linux-4.4.3\kernel\locking\semaphore.c

kernel\linux\linux-4.4.3\include\linux\semaphore.h

DOWN操作:linux內(nèi)核中,對信號量的DOWN操作有如下幾種:

1、void down(struct semaphore *sem); //不可中斷

down接口用于請求一個信號量。此函數(shù)的調(diào)用將會到致調(diào)用線程的睡眠,??直到獲取到信號。同時,該函數(shù)的調(diào)用不允許中斷。
在此函數(shù)中首先進(jìn)行信號量資源數(shù)的查看,如果信號量數(shù)據(jù)(count)不為0,則把其減1,并返回,調(diào)用成功;否則調(diào)用__down進(jìn)行等待,調(diào)用者進(jìn)行睡眠。

2、int down_interruptible(struct semaphore *sem);//可中斷

該函數(shù)功能和down類似,不同之處為,down不會被信號(signal)打斷,但down_interruptible能被信號打斷,因此該函數(shù)有返回值來區(qū)分是正常返回還是被信號中斷,如果返回0,表示獲得信號量正常返回,如果被信號打斷,返回-EINTR。

?

3、int down_killable(struct semaphore *sem);//睡眠的進(jìn)程可以因為受到致命信號而被喚醒,中斷獲取信號量的操作。

down_killable與down_interruptible相近,最終傳入的__down_common的實參有所不同(TASK_KILLABLE和TASK_INTERRUPTIBLE),所以,在此不再進(jìn)行分析。

4、int down_trylock(struct semaphore *sem);//試圖獲取信號量,若無法獲得則直接返回1而不睡眠。返回0則 表示獲取到了信號量

down_trylock接口用于試著獲取一個信號量,但是,此接口不會引起調(diào)用者的睡眠。不管有無可用信號量,都馬上進(jìn)行返回,如果返回0,則獲取信號量成功,如果返回1,則獲取失敗。所以,在調(diào)用此接口時,必須進(jìn)行返回的值的查看,看是否獲取成功。

5、int down_timeout(struct semaphore *sem,long jiffies);//表示睡眠時間是有限制的,如果在jiffies指明的時間到期時仍然無法獲得信號量,則將返回錯誤碼。

down_timeout接口的實現(xiàn)過程與down接口的實現(xiàn)過程差不多,只是此接口?可以自定義超時時間,也就是如果在超時間內(nèi)不能得到信號量,調(diào)用者會因為超時而自行喚醒。其實現(xiàn)過程如下,請注意超時參數(shù)的傳入。其中TASK_UNINTERRUPTIBLE

在以上五種函數(shù)中,驅(qū)動程序使用的最頻繁的就是down_interruptible函數(shù),以下將對該函數(shù)進(jìn)行分析。

down_interruptible函數(shù)的定義如下:

函數(shù)分析:函數(shù)首先通過spin_lock_irqsave的調(diào)用來保證對sem->count操作的原子性。如果count>0,表示當(dāng)前進(jìn)程可以獲得信號量,將count的值減1然后退出。如果count不大于0,表明當(dāng)前進(jìn)程無法獲取信號量,則調(diào)用__down_interruptible,后者會繼續(xù)調(diào)用__down_common。

__down_common 函數(shù)定義如下:

static inline int __sched __down_common(struct semaphore *sem, longstate,longtimeout){struct task_struct *task= current;struct semaphore_waiterwaiter;list_add_tail(&waiter.list,&sem->wait_list);waiter.task = task;waiter.up = 0;for (;;) {if(signal_pending_state(state, task))gotointerrupted;if (timeout <=0)gototimed_out;__set_task_state(task,state);spin_unlock_irq(&sem->lock);timeout =schedule_timeout(timeout);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ù)分析:在__down_common函數(shù)數(shù)執(zhí)行了以下操作。

(1)將當(dāng)前進(jìn)程放到信號量成員變量wait_list所管理的隊列中。

(2)在一個for循環(huán)中把當(dāng)前的進(jìn)程狀態(tài)這是為TASK_INTERRUPTIBLE,在調(diào)用schedule_timeout使當(dāng)前進(jìn)程進(jìn)入睡眠狀態(tài),函數(shù)將停留在schedule_timeout調(diào)用上,知道再次被調(diào)度執(zhí)行。

(3) 當(dāng)該進(jìn)程再一次被調(diào)度時,按原因執(zhí)行相應(yīng)的操作:如果waiter.up不為0說明進(jìn)程被該信號量的up操作所喚醒,進(jìn)程可以獲得信號量。如果進(jìn)程是因為被用戶空間的信號所中斷或超時信號所引起的喚醒,則返回相應(yīng)的錯誤代碼。?

UP操作:LINUX內(nèi)核只提供了一個up函數(shù)

up函數(shù)定義如下:

void up(struct semaphore *sem){unsigned long flags;spin_lock_irqsave(&sem->lock,flags);if(likely(list_empty(&sem->wait_list)))sem->count++;else__up(sem);spin_unlock_irqrestore(&sem->lock,flags);}

函數(shù)分析:如果sem的wait_list隊列為空,則表明沒有其他進(jìn)程正在等待該信號量,那么只需要把sem的count加1即可。如果wait_list隊列不為空,則說明有其他進(jìn)程正睡眠在wait_list上等待該信號,此時調(diào)用__up(sem)來喚醒進(jìn)程:

__up()函數(shù)定義如下:

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

函數(shù)分析:在函數(shù)中,調(diào)用了wake_up_process來喚醒進(jìn)程,這樣進(jìn)程就從之前的__down_interruptible調(diào)用中的timeout=schedule_timeout(timeout)處醒來,wait-up=1, __down_interruptible返回0,進(jìn)程獲得了信號量。

up()與down()函數(shù)之間的聯(lián)系:由上面對兩個函數(shù)的分析可以知道,__down_common函數(shù)中timeout=schedule_timeout(timeout) 有著很重要的作用。

Note:一個進(jìn)程在調(diào)用down_interruptible()之后,如果sem<0,那么就進(jìn)入到可中斷的睡眠狀態(tài)并調(diào)度其它進(jìn)程運行, 但是一旦該進(jìn)程收到信號,那么就會從down_interruptible函數(shù)中返回。并標(biāo)記錯誤號為:-EINTR。一個形象的比喻:傳入的信號量為1好比天亮,如果當(dāng)前信號量為0,進(jìn)程睡眠,直到(信號量為1)天亮才醒,但是可能中途有個鬧鈴(信號)把你鬧醒。又如:小強(qiáng)下午放學(xué)回家,回家了就要開始吃飯嘛,這時就會有兩種情況:情況一:飯做好了,可以開始吃;情況二:當(dāng)他到廚房去的時候發(fā)現(xiàn)媽媽還在做,媽媽就對他說:“你先去睡會,待會做好了叫你?!毙?qiáng)就答應(yīng)去睡會,不過又說了一句:“睡的這段時間要是小紅來找我玩,你可以叫醒我?!毙?qiáng)就是down_interruptible,想吃飯就是獲取信號量,睡覺對應(yīng)這里的休眠,而小紅來找我玩就是中斷休眠。

使用可被中斷的信號量版本的意思是,萬一出現(xiàn)了semaphore的死鎖,還有機(jī)會用ctrl+c發(fā)出軟中斷,讓等待這個內(nèi)核驅(qū)動返回的用戶態(tài)進(jìn)程退出。而不是把整個系統(tǒng)都鎖住了。在休眠時,能被中斷信號終止,這個進(jìn)程是可以接受中斷信號的!比如你在命令行中輸入# sleep 10000,按下ctrl + c,就給上面的進(jìn)程發(fā)送了進(jìn)程終止信號。信號發(fā)送給用戶空間,然后通過系統(tǒng)調(diào)用,會把這個信號傳給遞給驅(qū)動。信號只能發(fā)送給用戶空間,無權(quán)直接發(fā)送給內(nèi)核的,那1G的內(nèi)核空間,我們是無法直接去操作的。 --------------------- 本文來自 liuxd3000 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/liuxd3000/article/details/17913363?utm_source=copy

總結(jié)

以上是生活随笔為你收集整理的信号量机制中的down和up函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。