| 出招表七:信號量(信號量其實和自旋鎖是一樣的,就是有一點不同:當獲取不到信號量時,進程不會原地打轉而是進入休眠等待狀態(tài)) Linux系統(tǒng)中與信號量相關的操作主要有一下4種: 1)定義信號量 struct semaphore sem; 2)初始化信號量 void sema_init (struct semphore *sem, int val); //設置sem為val void init_MUTEX(struct semaphore *sem); //初始化一個用戶互斥的信號量sem設置為1 void init_MUTEX_LOCKED(struct semaphore *sem); //初始化一個用戶互斥的信號量sem設置為0 DECLARE_MUTEX(name); //該宏定義信號量name并初始化1 DECLARE_MUTEX_LOCKED(name); //該宏定義信號量name并初始化0 3)獲得信號量 void down(struct semaphore *sem); //該函數用于獲取信號量sem,會導致睡眠,不能被信號打斷,所以不能在中斷上下文使用。 int down_interruptible(struct semaphore *sem); //因其進入睡眠狀態(tài)的進程能被信號打斷,信號也會導致該函數返回,這是返回非0。 int down_trylock(struct semaphore *sem);//嘗試獲得信號量sem,如果能夠獲得,就獲得并返回0,否則返回非0,不會導致調用者睡眠,可以在中斷上下文使用 一般這樣使用 if(down_interruptible(&sem)) { return - ERESTARTSYS; } 4)釋放信號量 void up(struct semaphore *sem); //釋放信號量sem,喚醒等待者 信號量一般這樣被使用,如下所示: //定義信號量 DECLARE_MUTEX(mount_sem); down(&mount_sem);//獲取信號量,保護臨界區(qū) … critical section //臨界區(qū) … up(&mount_sem); 好了,下邊給大家一個例子看看使用信號量來實現設備只能被一個進程打開的例子: static DECLARE_MUTEX(xxx_lock);//定義互斥鎖 static int xxx_open(struct inode *inode, struct file *filp) { … if(down_trylock(&xxx_lock)) //獲得打開鎖 return – EBUSY; //設備忙 … return 0;//成功 } 
 static int xxx_release(struct inode *inode, struct file *filp) { up(&xxx_lock); //釋放打開鎖 return 0; } 在上面介紹的有關信號量的操作中,我們提到了一個問題就是信號量的初始化問題,一般對信號量的初始化是沒有限制的,但如果信號量被初始化為0,則它可以用于同步,說到這里,就不得不介紹新的一招了 
 出招表八:同步(它意味著一個執(zhí)行單元的繼續(xù)執(zhí)行需要等待另一個執(zhí)行單元完成其事,保證了執(zhí)行的先后順序)      在這個圖中,執(zhí)行單元A執(zhí)行代碼區(qū)域b之前,必須等待執(zhí)行單元B執(zhí)行完代碼單元c,而信號量剛好可輔助完成這一同步過程. 
 這時你可能要問,像這樣的同步,在現實中可是常常遇到.比如,報名時必須等前一項完成了才能完成后一項..等等,是不是同步就這么一種方式啊.. 呵呵,真聰明,小菜終于長大了,成為大菜了.其實,Linux系統(tǒng)提供了一種更好的同步機制----完成量,好吧,看在你求學若渴的份上,就把它一起傳授給你了,不收費哦,呵呵 出招表九:完成量(completion),它用于一個執(zhí)行單元等待另一個執(zhí)行單元執(zhí)行完某事 使用方法:1)定義完成量 struct completion my_completion; 2)初始化 init_completion(&my_completion); //要是覺得這兩步麻煩,就再給你來個宏即定義又初始化DECLARE_COMPLETION(my_completion); 3)等待完成量 void wait_for_completion(structcompletion *c); //等待一個completion被喚醒 wait_for_completion_interruptible(struct completion *c); //可中斷的wait_for_completion unsigned long wait_for_completion_timeout(struct completion *x,unsigned long timeout); //帶超時處理的wait_for_completion 4)喚醒完成量 void complete(struct completion *c); //只喚醒一個等待的執(zhí)行單元。 void complete_all(struct completion *c); //喚醒所有等待這個完成量的執(zhí)行單元 瞧我這記性,說了這么多,怎么就忘了給出completion結構體呢: struct completion { unsigned int done;//標志是否已經做完,未做完就是負值,代表等待個數,完成為0 wait_queue_head_t wait; } 如果覺得不太理解,不過癮,就給你來張圖:     這下感覺怎樣,好多了吧... 說句真的,我都沒想到,這點東西要將那么久,雖然不愿意,但只能說:欲知后事如何,咱們下回接著再聊.. | 
|  | 
來自: 看風景D人 > 《linux內核開發(fā)理論貼》