当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读]Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:(1)直接编译进Linux内核,随同Linux启动时加载;(2)编译成一个可加载和删除的模块,使用i

Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:

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

(2)编译成一个可加载和删除的模块,使用insmod加载(modprobe和insmod命令类似,但依赖于相关的配置文件),rmmod删除。这种方式控制了内核的大小,而模块一旦被插入内核,它就和内核其他部分一样。

下面我们给出一个内核模块的例子:

#include //所有模块都需要的头文件

#include // init&exit相关宏

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将使用模块内定义的缺省值。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

2019年上映的《复仇者联盟4:终局之战》无疑是漫威和超级英雄粉丝心中的剧痛,该片中最受观众喜爱的钢铁侠为了打败灭霸,一个响指也夺走了自己的生命。影片最后,复联成员们还为钢铁侠举办了一个葬礼,一众英雄出席让人泪奔。钢铁侠...

关键字: 漫威 HELLO OS

(全球TMT2022年8月15日讯)浪潮信息加入了 OCP Hardware Management Module (硬件管理模块)项目组,参与DC-SCM2.0规范的制定与完善,在产品研发中对DC-SCM标准进行了设计...

关键字: DC HARDWARE MANAGEMENT MODULE

北京2022年8月15日 /美通社/ -- 随着算力需求的多元化以及安全攻击技术的不断演变发展,在硬件层面强化安全控制与管理成为数据中心高效运营的重要支撑。但同时,多元算力带来硬件平台设计的组合复杂多样,相应的安全管理单...

关键字: 安全管理 数据中心 DC MODULE

来源:百问科技❞Linux内核源码文件繁多,搞不清Makefile、Kconfig、.config间的关系,不了解内核编译体系,编译修改内核有问题无从下手,自己写的驱动不知道怎么编进内核,不知道怎么配置内核,这些问题都和...

关键字: CONFIG HELLO MAKEFILE WORLD

1、聊一聊 今天为大家介绍数据驱动编程技巧,能够帮助大家在平时写出高质量的代码。 2、什么是数据驱动编程     作者一直觉得"没有设计思想的代码是没有灵魂的",所以在这么多年的程序设计中一般首先设计程序架构然后再进行编...

关键字: 数据驱动 驱动编程

  ospf报文   OSPF协议使用一种称之为Hello的报文来建立和维护相邻邻居路由器之间的链接关系。这个报文很简单的,容量很小,仅用来向邻居路由器证明自己的存在,就像人与人之间的打

关键字: OS 路由器 HELLO 数据库

手机钱包是区块链生态的重要一环,Hello团队作为社区领先的开发团队,针对比特股特性开发的SuperONE是基于区块链的数字资产投资管理平台,我们的目标是为用户提供更加安全、更加透明、去中心化的

关键字: 区块链 数字资产 SUPER HELLO

Hellokimi定位是做全球区块链游戏综合服务平台,我们的目标是成为区块链游戏领域领先的开发商和综合服务平台。我们是国内资深的原创游戏开发团队,深耕游戏行业十几年,有较深的游戏技术沉淀和行业资

关键字: 区块链 HELLO 开发者 游戏开发

在今天于上海举办的世界人工智能大会上,微软执行副总裁Harry Shum透露,Hololens 2将于9月发售。 Hololens 2发布于今年2月的MWC 2019大展,定价3500美

关键字: 微软 HOLOLENS HELLO Windows

01 前言 STM32上hello world,说白了就是使用串口向PC上的上位机软件或者串口调试助手发送字符串。 串口的使用方法百度一下就能知道了,简单来说就是下面这样。 uint8_t buff[BUFF_SIZE]...

关键字: STM32 HELLO WORLD BUF
关闭
关闭