linux中最简单的休眠方式:
wait_event(queue, condition) /* 进程将被置于非中断休眠(uninterruptible sleep)*/
wait_event_interruptible(queue, condition) /*进程可被信号中断休眠,返回非0值表示休眠被信号中断*/
wait_event_timeout(queue, condition, timeout) /*等待限定时间jiffy,condition满足其一返回0*/
wait_event_interruptible_timeout(queue, condition, timeout)
queue是等待队列头,传值方式
condition是任意一个布尔表达式,在休眠前后多次对condition求值,为真则唤醒
唤醒进程的基本函数:
void wake_up(wait_queue_head_t *queue); /*唤醒等待在给定queue上的所有进程*/
void wake_up_interruptible(wait_queue_head_t *queue);
总结一下Linux等待等列用法:
1、定义:wait_queue_head_t my_queue;
2、初始化 init_waitqueue_head(&my_queue);
3、在一个函数里面等待:wait_event_interruptible(queue, condition) ;(别在中断里面调用)
4、在另一个函数里面唤醒:wake_up_interruptible(wait_queue_head_t *queue); (这个可以在中断调用,去唤醒别的进程,特别是DMA操作等)
最后附上一个小的模板:
struct xxx_dev { struct cdev cdev; wait_queue_head_t r_wait; wait_queue_head_t w_wait; bool have_data; }; struct xxx_dev *xxx_devp; static ssize_t xxx_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) { struct xxx_dev *dev = filp->private_data; ...... /* 注意:使用的while,而不是if */ while(!have_data) { /* 如果用户设置了非阻塞的方式,则不需要调用等待队列 */ if (filp->f_flags & O_NONBLOCK) return -EAGAIN; /* interruptible:进程的唤醒有可能是其他信号 */ else wait_event_interruptible(xxx_devp->r_wait,have_data); } ...... } static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos) { struct xxx_dev *dev = filp->private_data; ...... have_data = true; wake_up_interruptible(&xxx_devp->r_wait); /* 唤醒等待队列 */ ...... } static int memdev_init(void) { ...... xxx_devp = kmalloc(sizeof(struct xxx_dev), GFP_KERNEL); ...... xxx_devp->have_data = false; init_waitqueue_head(&xxx_devp->r_wait); /*初始化读等待队列头 */ init_waitqueue_head(&xxx_devp->w_wait); /*初始化写等待队列头 */ ...... }