- 论坛徽章:
- 0
|
20可用积分
最近异想天开,想做一个内核模块,以实现完全异步IO。(并没有什么特别的需求,仅仅是想做点东西,熟悉一下内核态的编程。)
linux内核提供了异步IO的接口,但是这并不是完全的异步IO,仅仅是提供了一种异步通知机制,通知fd可读、可写、或出错。而用户程序得到这个通知后,还需要调用read/write去同步完成读写。
而完全的异步IO应该是:用户程序调用read/write接口;不管指定的fd是否可读可写,系统调用直接返回;内核记录下read/write传入的参数(file,buffer,size)并完成实际的读写过程(可能需要等待),然后向用户程序发信号通知;用户程序得到信号通知后,直接使用buffer里面的数据即可。
按我的想法,实现这个完全异步IO的内核模块注册为一个cdev。
用户使用完全异步IO的方式如下:
1、打开这个设备,获得一个设备fd;
2、通过ioctl接口,将另一个实际需要读写的fd(记为fd2)“绑定”到这个设备fd上;
3、设置fd2的f_owner,指定异步通知的对象,并注册对应的信号处理过程;
4、对这个设备fd进行一次读写操作,读写操作不阻塞。用户程序在信号处理过程中处理fd的读写结果;
内核模块的实现如下:
1、init:创建一个内核线程,作为工作线程;
2、open:创建一个异步任务描述对象,存放在file->private_data;
3、ioctl:设置异步任务描述对象的属性,记录到fd2的file结构;
4、read/write:设置异步任务描述对象的属性,记录buffer/size,并向工作线程添加这个任务;
5、工作线程:通过调用对应的“绑定”的fd2的poll接口,判断其是否可读/可写。如果可读/可写,则调用vfs_read/vfs_write进行读写,然后发送信号通知;如果不可读/可写,工作线程挂起等待(类似sys_poll的做法);
大体的想法就是这样。但是其中有一点感觉很难实现:异步任务描述对象中保存的buffer地址是一个虚拟地址,这个地址仅仅在对应的进程上下文中才有效,在工作线程中是无效的,不能使用copy_to_user……
这个问题该如何解决呢?希望听听大家的见解,望不吝赐教~ |
最佳答案
查看完整内容
用户态传地址再在内核态转物理地址本身就不是个标准做法。通常做法是driver分配内存供用户态map。其实不用搞那么复杂,你可以在内核中分配一块和用户态大小一样的内存,先写到这里面,最后在copy到用户态传下来的地址中。
|