1,等待队列
1)定义等待队列头
wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue);
//定义并初始化宏
DECLEAR_WAIT_QUEUE_HEAD(name);
DECLEAR_WAITQUEUE(name,tsk);//此定义宏中的参数 不需要事先自己定义
void fastcall add_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);
void fastcall remove_wait_queue(wait_queue_head_t *q,wait_queue_t *wait);
wait_event(queue,condition);
wait_event_interruptible(queue,condition);
wait_event_timeout(queue,condition);
wait_event_interruptible_timeout(queue,condition);
//等待第一个参数queue作为等待队列头的等待队列被唤醒,且第二个参数
condition必须满足,否则阻塞
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
//上述操作会唤醒以queue作为等待队列头的所有等待队列中所有属于该等
带队列头的等待队列对应的进程
注意:wake_up()应该与wait_event()或wait_event_timeout()成对使用
interruptible也是成对使用。
sleep_on(wait_queue_head_t *q);
interruptible_sleep_on(wait_queue_head_t *q);
//sleep_on()函数的作用就是将目前进程的状态置为TASK_UNINTERRUPTIBLE
并定义一个等待队列,之后把它附属到等待队列q,直到资源可获得,q引导
的等待队列被唤醒。sleep_on()与wake_up()应成对使用
等待队列的典型应用
struct glb {
struct cdev cdev;
unsigned int current_len;
unsigned char mem[100];
struct semaphore sem;
wait_queue_head_t r_wait;
// wait_queue_head_t w_wait;
};
size_t xxx_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos)
{
struct glb *dev = filp->private_data;
DECLEAR_WAITQUEUE(wait,current);// 定义等待队列
down(&dev->sem);
add_wait_queue(&dev->r_wait,&wait);//进入读的等待队列
if(dev->current_len == 0){
if(filp->f_flags & O_NONBLOCK){//非阻塞访问
ret = -EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);//修改进程为睡眠
up(&dev->sem);
schedule();//调度其他进程
if(signal_pending(current)){//如果信号唤醒
ret = -ERESTARTSYS;
goto out2;
}
down(&dev->sem);//重新获取信号量
}
if(count > dev->current_len)
count = dev->current_len;
if(copy_to_user(buf,dev->mem,count)){
ret = -EFAULT;
goto out;
}else{
memcpy(dev->mem,dev->mem+count,dev->current_len-count);
//数据前移
dev->count_len -= count;//有效数据减少
wake_up_interruptible(&dev->w_wait);//唤醒写等待队列,注意:读队列的唤醒应该在xxx_write上执行,当写入了数据,说明可以读了
ret = count;
}
//非阻塞及出错处理及程序结束处理
out: up(&dev->sem);
out2: remove_wait_queue(&dev->w_wait,&wait);
set_current_state(TASK_RUNNING);
return ret;
}