文件io的模型,阻塞,非阻塞,多路复用,异步信号
异步信号通知:当有数据到的时候,驱动回发送信号sigio给应用,就可以异步去读写数据,不用主动去读写。app侧
①设置信号的处理方法SIGIO()
void catch_signale(int signo){if(signo == SIGIO) ...//读数据}
signal(SIGIO,catch_signale);
②设置信号IO的属主进程-getpid
fcntl(fd,F_SETOWN,getpid());
③设置异步信号模式-将io模式设置成异步模式
int flags = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,flags | FASYNC);
驱动--发送信号--需要和进程进行关联--记录信号该发送给谁
.fasync = key_drv_fasync,
key_drv_fasync(int fd,struct file* file, int on)
retuen = fasync_helper(fd ,file,on,struct fasync_struct ** fapp)
在有数据的时候发送信号
kill_fasync(struct fasync_struct ** fapp , SIGIO, POLLIN)
中断的上下半部:中断处理短不了,将耗时的一些操作延后,
实现方式 :softirq 软中断,处理的比较快,内核级别的机制,需要修改整个内核代码,不推荐也不常见; tasklet 内部实现实际调用了softirq ;工作队列workqueue--中断下半部
等待队列主要是用于处理阻塞文件模型的
softirq 有属性和方法 会放在内核线程当中,是通过链表的方式进行管理,也叫启动下半部,运行在中断上下文当中,不可以执行休眠的函数sleep等
工作队列 有属性和方法 会放在内核线程当中 ,是通过工作队列的方式进行管理,运行在进程的上下文,是可以进行休眠的
struct tasklet_struct
{
struct tasklet_struct *next; //通过链表的方式进行管理
unsigned long state; //属性
atomic_t count; //属性
void (*func)(unsigned long); //下半部的方法,在上半部中放入到内核线程中---启动
unsigned long data;
};
struct tasklet_struct mytasklet;
tasklet_init(struct tasklet_struct * t, void(* func)(unsigned long), unsigned long data) //初始化
tasklet_schedule(struct tasklet_struct * t)//启动中断下半部
tasklet_kill(struct tasklet_struct * t)// 移除中断下半部
工作队列
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
struct work_struct mywork;
INIT_WORK(struct work_struct *work , work_func_t func) //初始化
schedule_work(struct work_struct * work) //启动中断下半部