您的位置 首页 软件

浅显易懂linux设备驱动编程

Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:(1)直接编译进Linux内核,随同Linux启动时加载;(2)编译成一个可加载

Linux设备驱动归于内核的一部分,Linux内核的一个模块能够以两种方法被编译和加载:

(1)直接编译进Linux内核,伴随Linux启动时加载;

(2)编译成一个可加载和删去的模块,运用insmod加载(modprobe和insmod指令相似,但依赖于相关的配置文件),rmmod删去。这种方法操控了内核的巨细,而模块一旦被刺进内核,它就和内核其他部分相同。

下面咱们给出一个内核模块的比方:

#include //一切模块都需求的头文件

#include // initexit相关宏

MODULE_LICENSE(GPL);

static int __init hello_init (void)

{

printk(Hello module init\n);

return 0;

}

static void __exit hello_exit (void)

{

printk(Hello module exit\n);

}

module_init(hello_init);

module_exit(hello_exit);

剖析上述程序,发现一个Linux内核模块需包括模块初始化和模块卸载函数,前者在insmod的时分运转,后者在rmmod的时分运转。初始化与卸载函数必须在宏module_init和module_exit运用前界说,不然会呈现编译过错。

程序中的MODULE_LICENSE(GPL)用于声明模块的许可证。

假如要把上述程序编译为一个运转时加载和删去的模块,则编译指令为:

gcc -D__KERNEL__ -DMODULE -DLINUX -I /usr/local/src/linux2.4/include -c -o hello.o hello.c

由此可见,Linux内核模块的编译需求给gcc指示-D__KERNEL__ -DMODULE -DLINUX参数。-I选项跟着Linux内核源代码中Include目录的途径。

下列指令将可加载hello模块:

insmod ./hello.o

下列指令完结相反进程:

rmmod hello

假如要将其直接编译入Linux内核,则需求将源代码文件仿制入Linux内核源代码的相应途径里,并修正Makefile。

咱们有必要弥补一下Linux内核编程的一些基本常识:

内存

在Linux内核形式下,咱们不能运用用户态的malloc()和free()函数请求和开释内存。进行内核编程时,最常用的内存请求和开释函数为在include/linux/kernel.h文件中声明的kmalloc()和kfree(),其原型为:

void *kmalloc(unsigned int len, int priority);

void kfree(void *__ptr);

kmalloc的priority参数一般设置为GFP_KERNEL,假如在中止服务程序里请求内存则要用GFP_ATOMIC参数,因为运用GFP_KERNEL参数或许会引起睡觉,不能用于非进程上下文中(在中止中是不答应睡觉的)。

因为内核态和用户态运用不同的内存界说,所以二者之间不能直接拜访对方的内存。而应该运用Linux中的用户和内核态内存交互函数(这些函数在include/asm/uaccess.h中被声明):

unsigned long copy_from_user(void *to, const void *from, unsigned long n);

unsigned long copy_to_user (void * to, void * from, unsigned long len);

copy_from_user、copy_to_user函数回来不能被仿制的字节数,因而,假如彻底仿制成功,回来值为0。

include/asm/uaccess.h中界说的put_user和get_user用于内核空间和用户空间的单值交互(如char、int、long)。

这儿给出的仅仅是关于内核中内存办理的皮裘,关于Linux内存办理的更多细节常识,咱们会在本文第9节《内存与I/O操作》进行愈加深化地介绍。

输出

在内核编程中,咱们不能运用用户态C库函数中的printf()函数输出信息,而只能运用printk()。可是,内核中printk()函数的规划意图并不是为了和用户沟通,它实际上是内核的一种日志机制,用来记录下日志信息或许给出正告提示。

每个printk都会有个优先级,内核一共有8个优先级,它们都有对应的宏界说。假如未指定优先级,内核会挑选默许的优先级 DEFAULT_MESSAGE_LOGLEVEL。假如优先级数字比int console_loglevel变量小的话,音讯就会打印到操控台上。假如syslogd和klogd看护进程在运转的话,则不管是否向操控台输出,音讯都会被追加进/var/log/messages文件。klogd 只处理内核音讯,syslogd 处理其他体系音讯,比方应用程序。

模块参数

2.4内核下,include/linux/module.h中界说的宏MODULE_PARM(var,type) 用于向模块传递指令行参数。var为承受参数值的变量名,type为采纳如下格局的字符串[min[-max]]{b,h,i,l,s}。min及max 用于表明当参数为数组类型时,答应输入的数组元素的个数规模;b:byte;h:short;i:int;l:long;s:string。

在装载内核模块时,用户能够向模块传递一些参数:

insmod modname var=value

假如用户未指定参数,var将运用模块内界说的缺省值。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/ruanjian/298194.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部