Linux字符驱动-IO模型

Linux字符驱动-IO模型

1、阻塞

	实现方法
	**一、手动实现**
  1. 定义一个等待队列头,并初始化等待队列头
wait_queue_head_t wq;
init_waitqueue_head(&wq);
  1. 定义一个等待队列项,添加等待队列项到等待队列
DECLARE_WAITQUEUE(r_wait,current);	//r_wait表示等待队列项的名称,current表示当前进程
add_wait_queue(&wq,&r_wait);	
  1. 判断应用层是否以阻塞方式打开文件
if(file->f_flags & O_NONBLOCK){
	//判断条件成立后表示用户是以非阻塞的方式打开的文件
	return -EAGAIN;
}
	//判断条件不成立表示用户是以非阻塞的方式打开的文件
  1. 若应用层以阻塞方式打开文件,切换进程的状态
set_current_state(TASK_INTERRUPTIBLE);  //可中断的等待态
  1. 主动放弃CPU,等待进程被唤醒
schedule(); //主动放弃CPU
  1. 被唤醒
//可以被信号唤醒,也可以被中断唤醒(被中断唤醒表示数据已经住哪被好了)
//wake_up(x);
wake_up_interruptible(x);
  1. 唤醒后判断是否是被信号唤醒,如果不是信号被唤醒,表示数据已经准备好,可以进行数据的拷贝
if(signal_pending(current)){
	//判断条件成立,表示是被信号唤醒的
}
//判断条件不成立,表示不是被信号唤醒的,可以进行数据的拷贝
  1. 数据拷贝前将进程状态切换为运行状态
set_current_state(TASK_RUNNING);	//切换进程为运行态
  1. 拷贝数据
copy_to_user();
  1. 删除等待队列项
remove_wait_queue();
**一、自动实现**
  1. 定义等待队列头
wait_queue_head_t wq;
  1. 定义一个标志位,代表阻塞或者被唤醒
int condition = 0;
//condition等于0的时候表示阻塞,condition为真的时候表示被唤醒
  1. 实现阻塞
//wait_event(wq,condition);
wait_event_interrupt(wq,condition);

2、非阻塞

非阻塞的方式实现比较简单,只需要在应用层打开文件时使用O_NONBLOCK

open("/dev/char",O_RDWR|O_NONBLOCK);

3、IO多路复用

应用层用于监听多个文件描述符的函数有select、poll、epoll,这三个函数都调用驱动层的poll函数;
实现方法
  1. 定义等待队列头,并初始化
  2. 提交等待队列头
poll_wait();
  1. 当条件为真时,置位mask
    POLLIN ------表示用户可读
    POLLOUT------表示用户可写

4、异步通知

应用层代码实现:
1.添加信号处理函数

sighander_t signal(int signum,sighander_t hander);
2.设置信号发送的进程
fcntl(fd,F_SETOWN,getpid());
3.调用fasync函数
flags = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,flags|FASYNC);

内核层代码实现:
1.异步通知结构体的初始化
fasync_helper(fd,filp,on,fapp);
2.发送信号
kill_fasync();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值