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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

(十)Linux之等待队列

發(fā)布時(shí)間:2025/3/8 linux 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (十)Linux之等待队列 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

(一)阻塞和非阻塞

阻塞:執(zhí)行設(shè)備操作時(shí),若不能獲得資源,則掛起進(jìn)程進(jìn)入休眠直到滿足可操作的條件后再操作。
非阻塞:進(jìn)程在不能進(jìn)行設(shè)備操作時(shí),并不掛起,它要么放棄,要么不停地查詢,直至可以進(jìn)行操作為止。

(二)為什么學(xué)習(xí)等待隊(duì)列

在講解等待隊(duì)列的作用之前先來看一下內(nèi)核的休眠機(jī)制:

正在運(yùn)行的進(jìn)程讓出CPU,休眠的進(jìn)程會(huì)被內(nèi)核擱置在一邊,只有當(dāng)內(nèi)核再次把休眠的進(jìn)程喚醒, 進(jìn)程才會(huì)重新在CPU運(yùn)行,這是內(nèi)核中的進(jìn)程調(diào)度 一個(gè)CPU在同一時(shí)間只能有一個(gè)進(jìn)程在運(yùn)行,內(nèi)核將所有的進(jìn)程按一定的算法將CPU輪流的給每個(gè) 進(jìn)程使用,而休眠就是進(jìn)程沒有被運(yùn)行時(shí)的一種形式。在休眠下,進(jìn)程不占用CPU,等待被喚醒。

當(dāng)一個(gè)進(jìn)程休眠時(shí),其他進(jìn)程為了能夠喚醒休眠的進(jìn)程,它必須知道休眠的進(jìn)程在哪里,出于這樣的原因,需要有一個(gè)稱為等待隊(duì)列的結(jié)構(gòu)體。等待隊(duì)列是一個(gè)存放著等待某個(gè)特定事件進(jìn)程鏈表。所以等待隊(duì)列相當(dāng)于休眠進(jìn)程的鏈表,需要手動(dòng)進(jìn)行操作

它的作用主要是:實(shí)現(xiàn)中斷處理、進(jìn)程同步及延時(shí)進(jìn)程

(三)等待隊(duì)列的相關(guān)接口

等待隊(duì)列頭數(shù)據(jù)結(jié)構(gòu):

struct __wait_queue_head {spinlock_t lock; //自旋鎖機(jī)制struct list_head task_list; }; typedef struct __wait_queue_head wait_queue_head_t; wait_queue_head_t:即為等待隊(duì)列頭的數(shù)據(jù)類型

初始化等待隊(duì)列頭:

靜態(tài)定義等待隊(duì)列頭并初始化: #define DECLARE_WAIT_QUEUE_HEAD(name) \wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)動(dòng)態(tài)定以并初始化:#define init_waitqueue_head(q) \do { \static struct lock_class_key __key; \\__init_waitqueue_head((q), #q, &__key); \} while (0)

休眠等待隊(duì)列wait_event或wait_event_interruptible:

/*** wait_event - sleep until a condition gets true* @wq: the waitqueue to wait on* @condition: a C expression for the event to wait for** The process is put to sleep (TASK_UNINTERRUPTIBLE) until the* @condition evaluates to true. The @condition is checked each time* the waitqueue @wq is woken up.** wake_up() has to be called after changing any variable that could* change the result of the wait condition.*/ #define wait_event(wq, condition) \ do { \if (condition) //判斷條件是否滿足,如果滿足則退出等待 \break; \__wait_event(wq, condition); //如果不滿足,則進(jìn)入__wait_event宏 \ } while (0)#define __wait_event(wq, condition) \ do { \DEFINE_WAIT(__wait); \/*定義并且初始化等待隊(duì)列項(xiàng),后面我們會(huì)將這個(gè)等待隊(duì)列項(xiàng)加入我們的等待隊(duì)列當(dāng)中,同時(shí)在初始化的過程中,會(huì)定義func函數(shù)的調(diào)用函數(shù)autoremove_wake_function函數(shù),該函數(shù)會(huì)調(diào)用default_wake_function函數(shù)。*/ \for (;;) { \prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \/*調(diào)用prepare_to_wait函數(shù),將等待項(xiàng)加入等待隊(duì)列當(dāng)中,并將進(jìn)程狀態(tài)置為不可中斷TASK_UNINTERRUPTIBLE;*/ if (condition) //繼續(xù)判斷條件是否滿足 \break; \schedule(); //如果不滿足,則交出CPU的控制權(quán),使當(dāng)前進(jìn)程進(jìn)入休眠狀態(tài) \} \finish_wait(&wq, &__wait);/**如果condition滿足,即沒有進(jìn)入休眠狀態(tài),跳出了上面的for循環(huán),便會(huì)將該等待隊(duì)列進(jìn)程設(shè)置為可運(yùn)行狀態(tài),并從其所在的等待隊(duì)列頭中刪除 */ \ } while (0)#define wait_event_interruptible(wq, condition) \ ({ /**如果condition為false,那么__wait_event_interruptible將會(huì)被執(zhí)行*/ \int __ret = 0; \if (!(condition)) \__wait_event_interruptible(wq, condition, __ret); \__ret; \ })

喚醒等待隊(duì)列節(jié)點(diǎn)wake_up_interruptible或wake_up:

#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key); /*** __wake_up - wake up threads blocked on a waitqueue.* @q: the waitqueue* @mode: which threads* @nr_exclusive: how many wake-one or wake-many threads to wake up* @key: is directly passed to the wakeup function** It may be assumed that this function implies a write memory barrier before* changing the task state if and only if any tasks are woken up.*//**定義wake_up函數(shù)宏,同時(shí)其需要一個(gè)wait_queue_head_t的結(jié)構(gòu)體指針,在該宏中調(diào)用__wake_up方法。*/ #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) #define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL) #define wake_up_all(x) __wake_up(x, TASK_NORMAL, 0, NULL)

加interruptible接口標(biāo)識(shí)喚醒可中斷

#define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL) #define wake_up_interruptible_nr(x, nr) __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL) #define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL) #define wake_up_interruptible_sync(x) __wake_up_sync((x), TASK_INTERRUPTIBLE, 1)

(四)如何實(shí)現(xiàn)等待隊(duì)列

1、創(chuàng)建等待隊(duì)列頭

//1.靜態(tài)定義并初始化 #define DECLARE_WAIT_QUEUE_HEAD(name) \wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)//2.動(dòng)態(tài)定以并初始化:wait_queue_head_t name;init_waitqueue_head(q)

默認(rèn)情況下會(huì)把當(dāng)前進(jìn)程作為等待任務(wù)放到等待隊(duì)列中
2、在需要休眠的地方調(diào)用休眠操作

wait_event 、 wait_event_timeout wait_event_interruptible(首選)

3、在滿條件的地方喚醒等待隊(duì)列

wake_up 、wake_up_interruptible

(五)實(shí)例代碼

chrdev.c

#include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/wait.h> #include <linux/sched.h> #include <linux/uaccess.h>#define CDEVCOUNT 5 #define CDEVNAME "cdevdevice" #define INODENAME "mycdev" int count=0; dev_t dev=0; int keyflag;//等待隊(duì)列第二個(gè)參數(shù) char keyvalue[4]={-1,-1,-1,-1}; struct cdev * cdev =NULL; struct class * cdevclass =NULL; wait_queue_head_t waithead;struct Key {unsigned int gpios;char * name;int num;unsigned int irq;};struct Key key[]={{EXYNOS4_GPX3(2),"K1",0},{EXYNOS4_GPX3(3),"K2",1},{EXYNOS4_GPX3(4),"K3",2},{EXYNOS4_GPX3(5),"K4",3},}; irqreturn_t key_handler(int irq, void * dev) {struct Key * tmp =(struct Key *)dev;int value[4];value[tmp->num]= gpio_get_value(tmp->gpios);gpio_set_value(EXYNOS4X12_GPM4(tmp->num),value[tmp->num]);keyflag = 1;keyvalue[tmp->num] = value[tmp->num];wake_up_interruptible(&waithead);printk("key%d value is %d\n",tmp->num,value[tmp->num]);printk("the current cpu is %d\n",smp_processor_id());return IRQ_HANDLED;}int cdev_open (struct inode *node, struct file *file) {printk("cdev_open is install\n");return 0; } ssize_t cdev_read (struct file *fp, char __user *buf, size_t size, loff_t *offset) {int ret =0;if((fp->f_flags & O_NONBLOCK)== O_NONBLOCK)//非阻塞{if(!keyflag)return -EAGAIN;}else//阻塞{wait_event_interruptible(waithead,keyflag);}keyflag =0;ret = copy_to_user(buf,keyvalue,4);if(ret <0)return -EFAULT;printk("cdev_read is install\n");return 0; } ssize_t cdev_write (struct file *fp, const char __user * buf, size_t size, loff_t *offset) {printk("cdev_write is install\n");return 0; } int cdev_release (struct inode *node, struct file *fp) {printk("cdev_release is install\n");return 0; } struct file_operations fop={.open=cdev_open,.read=cdev_read,.write=cdev_write,.release=cdev_release, };void mycdev_add(void) {//1.申請(qǐng)?jiān)O(shè)備號(hào)--動(dòng)態(tài)int ret =alloc_chrdev_region(&dev,0, CDEVCOUNT, CDEVNAME);if(ret)return ;//初始化cdev結(jié)構(gòu)體cdev = cdev_alloc();if(!cdev){goto out;}cdev_init(cdev,&fop);//添加字符設(shè)備到系統(tǒng)中ret =cdev_add(cdev,dev, CDEVCOUNT);if(ret){goto out1;}//創(chuàng)建設(shè)備類cdevclass = class_create(THIS_MODULE, INODENAME);if(IS_ERR(cdevclass)){goto out2;}for (count=0;count<CDEVCOUNT;count++)device_create(cdevclass, NULL, dev+count, NULL, "mydevice%d",count);out:unregister_chrdev_region(dev,CDEVCOUNT); return ; out1:unregister_chrdev_region(dev,CDEVCOUNT);kfree(cdev);return ; out2:cdev_del(cdev);unregister_chrdev_region(dev,CDEVCOUNT);kfree(cdev);return ;}static int __init dev_module_init(void) {int ret=0,i=0;unsigned long flags= IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_SHARED;for(i=0;i<4;i++){key[i].irq = gpio_to_irq(key[i].gpios);ret =request_irq(key[i].irq, key_handler,flags,key[i].name,(void *) &key[i]);}init_waitqueue_head(&waithead);//創(chuàng)建等待隊(duì)列頭mycdev_add();printk("this is dev_module_init \n");return 0; }static void __exit dev_module_cleanup(void) {int i=0;for(i=0;i<4;i++){key[i].irq = gpio_to_irq(key[i].gpios);free_irq(key[i].irq,(void *)&key[i]);}for(count=0;count<CDEVCOUNT;count++){device_destroy(cdevclass, dev+count);}class_destroy(cdevclass);cdev_del(cdev);unregister_chrdev_region(dev, CDEVCOUNT);kfree(cdev);printk("this is dev_module_cleanup\n"); }module_init(dev_module_init); module_exit(dev_module_cleanup); MODULE_LICENSE("GPL");

chr_app.c

#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>char status[]={-1,-1,-1,-1}; char key[]={-1,-1,-1,-1}; int main(int argc, char *argv[]) {int i=0,fd= open(argv[1],O_RDWR);if(fd== -1){perror("open");return -1;}while(1){if(read(fd,status,4)<0){printf("按鍵狀態(tài)未改變\n");sleep(1);continue;}for(i=0;i<4;i++){if(status[i] != key[i] ){printf("key%d is %s\n",i,status[i]?"up":"down");status[i]=key[i];}}}close(fd);return 0; }

Makefile

CFLAG =-C TARGET = chrdev TARGET1 = chr_app KERNEL = /mydriver/linux-3.5 obj-m += $(TARGET).oall:make $(CFLAG) $(KERNEL) M=$(PWD)arm-linux-gcc -o $(TARGET1) $(TARGET1).c clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean

本文章僅供學(xué)習(xí)交流用禁止用作商業(yè)用途,文中內(nèi)容來水枂編輯,如需轉(zhuǎn)載請(qǐng)告知,謝謝合作

微信公眾號(hào):zhjj0729

微博:文藝to青年

總結(jié)

以上是生活随笔為你收集整理的(十)Linux之等待队列的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 亚洲精品成a人在线观看 | 欧美成人免费在线观看 | 永久av在线| 国产aaa毛片 | 日日草夜夜草 | 午夜爽爽影院 | av资源站 | 国产一级片免费观看 | 美女张开腿让男人桶爽 | 国产精品亚洲成在人线 | 自拍偷拍精品 | 精品无码一级毛片免费 | 7色av | 欧美成人免费视频 | 苍井空浴缸大战猛男120分钟 | 伦理片波多野结衣 | www.av黄色| 蜜桃视频免费网站 | 日韩无码精品一区二区 | 亚洲一区影院 | 玩弄人妻少妇500系列视频 | 99色婷婷 | 免费裸体视频女性 | 青青草视频国产 | 精品欧美久久久 | 三级免费观看 | 直接看av的网站 | 超碰91在线观看 | 大尺度av在线 | 妞妞影视 | 国产伦精品一区二区三区高清 | 国产寡妇亲子伦一区二区三区四区 | 99久久精 | 国产高清视频一区二区 | 日韩在线观看免费全 | 亚洲av无码潮喷在线观看 | 可以免费看的av网站 | www.日韩欧美 | 精品国产乱子伦一区二区 | 日本国产网站 | 国产免费网 | 日本美女性高潮 | 爽爽av| 国产精品资源网站 | 伊人毛片 | 精品久久不卡 | 玖玖热在线视频 | 亚洲爱v | 五十路japanese55丰满 | 毛片无码免费无码播放 | 午夜三区 | 亚洲欧美另类自拍 | 亚洲精品一级二级 | 成人欧美视频 | 日韩精品一区二区三区色欲av | 总裁边开会边做小娇妻h | 亚洲一区二区三区加勒比 | 欧洲自拍偷拍 | 麻豆系列在线观看 | 韩国三级hd中文字幕 | 妖精视频一区二区三区 | 人人爱人人 | 日韩中文字幕影院 | 欧洲成人综合 | www.youjizz.com在线观看 | 国产午夜无码视频在线观看 | 中文字幕免费观看视频 | 99久久久无码国产精品性色戒 | 国产人妖在线播放 | 国产乱在线| 久久青青草原 | 国产精品第八页 | 国产精品扒开腿做爽爽爽男男 | 影音先锋波多野结衣 | 蜜臀国产AV天堂久久无码蜜臀 | 99热这里只有精品4 精品国产黄色 | 精品亚洲国产成av人片传媒 | 中文字幕视频免费 | 国产91热爆ts人妖系列 | 欧美日韩精品在线观看 | 亚洲一二区 | 国产精品大屁股白浆一区 | 亚洲美女自拍偷拍 | 极品美妇后花庭翘臀娇吟小说 | 网友自拍一区 | 欧美激情视频一区二区三区不卡 | 伊人啪啪网 | 亚洲视频1 | 99免费观看视频 | 东京久久久 | 波多野结衣激情视频 | 一本色道久久综合狠狠躁 | 黄色三级在线播放 | 18在线观看视频 | 欧洲一区二区视频 | 国产成人啪精品 | 又大又长粗又爽又黄少妇视频 | 人人搞人人插 | 五月婷综合网 |