linux用户态与内核态通讯及如何编写内核模块

通讯方式:procfs/socket/syscall/IOCTL

常用的是socket/syscall/ioctl.

ioctl机制,ioctl机制可以在驱动中扩展特定的ioctl消息,用于将一些状态从内核反应到用户态。Ioctl有很好的数据同步保护机制,不要担心内核和用户层的数据访问冲突,但是ioctl不适合传输大量的数据,通过和内存映射结合可以很好的完成大量数据交换过程。但是,ioctl的发起方一定是在用户态,因此如果需要内核态主动发起一个通知消息给用户层,则非常的麻烦。可能需要用户态程序采用轮询机制不停的ioctl。

采用内存映射的方式,将内核地址映射到用户态。这种方式最直接,可以适用大量的数据传输机制。这种方式的缺点是很难进行“业务控制”,没有一种可靠的机制保障内核和用户态的调动同步,比如信号量等都不能跨内核、用户层使用。因此内存映射机制一般需要配合一种“消息机制”来控制数据的读取,比如采用“消息”类型的短数据通道来完成一个可靠的数据读取功能。

编写内核模块:

编写一个内核模块首先要确保内核打开了CONFIG_MODULES宏,并且已经编译了内核。

需要添加头文件<linux/module.h>

编写内核模块必须要实现一个init方法和一个exit方法。由于模块是可以在内核运行过程中动态的加载和卸载的,因此,在加载模块时要指定一个init方法作为入口函数,同样的,在卸载模块的时候,exit方法可以做一些清理工作。

一个最简单的内核模块的实现如下:

#include <linux/module.h>  
  
static int __init xxx_init(void)  
{  
    /* TODO: 在这个模块中你想做的事情 */  
    return 0;  
}  
  
static void __exit xxx_exit(void)  
{  
    /* TODO: 卸载这个模块时需要做的清理工作 */
}  

module_init(xxx_init);  
module_exit(xxx_exit);  

编写Makefile
Makefile

obj-m += testm.o

编译

make -C /lib/modules/`uname -r`/build M=$PWD

安装

make -C /lib/modules/`uname -r`/build M=$PWD modules_install

模块A中定义了函数funcA(),在模块B中想使用这个函数,那么在编写模块A时,就要使用EXPORT_SYMBOL宏将funcA()函数导出。在模块A中代码的写法:

int funcA(void)  
{  
       printk("funcA inmodule A.\n");  
       return 0;  
}  
EXPORT_SYMBOL(funcA);

猜你喜欢

转载自blog.csdn.net/weixin_38679007/article/details/80625736