IO模型
1:阻塞式IO
阻塞操作 指执行设备操作时若不能获取进程资源则进行睡眠,满足条件了唤醒继续执行。
2,非阻塞式IO
非阻塞操作 指进程在不能进行设备操作时并不睡眠而是立刻返回结果。
3,io多路复用
4,信号驱动IO
阻塞IO依赖内核里面的等待队列(一下为API)
定义“等待队列头”
wait_queue_head_t my_queue;
初始化“等待队列头”
init_waitqueue_head(&my_queue);
定义等待队列
DECLARE_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) // queue 等待队列,condition唤醒条件
wait_event_interruptible(queue, condition) // 等待过程中,可以被中断//直到condition为真就会唤醒队列继续执行
wait_event_timeout(queue, condition, timeout)
wait_event_interruptible_timeout(queue, condition, timeout)
// 阻塞睡眠,直到条件变为真
唤醒队列
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
1阻塞io实现
1:在驱动初始化时初始化等待队列
sema_init(&sem, 0);
init_waitqueue_head(&wq);
2:申请资源(xxx_read)
if(counter == 0){
if(wait_event_interruptible(wq, counter != 0) != 0){
return -ERESTARTSYS;
}
}
//申请资源
down_interruptible(&sem);//申请资源的过程中可以被中断
3:生产资源(xxx_xxx_write)
if(copy_from_user(kbuf, buffer, size) != 0)
{
printk(“Failed to copy_from_user.\n”);
return -1;
}
printk(“kbuf:%s\n”, kbuf);
counter = size;
up(&sem);
wake_up_interruptible(&wq);
这样就实现了简单的阻塞io
2:非阻塞io实现
非阻塞式IO
1,应用程序,设置非阻塞标志位
open(… , O_NONBLOCK); // 非阻塞打开方式
使用fcntl设置非阻塞标志位
int fcntl(int fd, int cmd, ... /* arg */ );
int flags = 0;
flags = fcn