Linux驱动入门——构建和运行模块
来源:互联网 发布:淘宝销量累计规则 编辑:程序博客网 时间:2024/05/29 09:24
Hello world模块
本文介绍如何向内核中添加一个hello模块。该模块的功能是在模块加载时,向系统日志输出“hello world\n” 在模块卸载时输出“Good bye,cruel world!".
一个模块源代码一般有含有一个init函数(加载时调用)和一个exit函数(卸载时调用)。这两个函数由分别由宏module_init和module_exit调用。因而一个简单的Hello world模块源代码如下:
#include <linux/init.h><span style="white-space:pre"></span>//这个头文件包含了你的模块初始化与清除的函数#include <linux/module.h><span style="white-space:pre"></span>//这个头文件包含了许多与模块加载有关的符号与函数的定义<span style="white-space:pre"></span>//如果模块需要参数传递,还可以参考moduleparam.h MODULE_LICENSE("GPL");<span style="white-space:pre"></span>//表明本模块带有一个GPL的自由许可证,没有这行,加载模块时内核可能会抱怨MODULE_AUTHOR("Windeal")<span style="white-space:pre"></span>//author //模块加载时调用的函数static int hello_init(void){ printk(KERN_ALERT "Hello world!\n");//printk是内核函数接口,会将内容输出到系统日志,KERN_ALERT表明输出优先级,printk也是行缓冲的 return 0;}//模块卸载时调用的函数static void hello_exit(void){ printk(KERN_ALERT "Good bye, cruel world!\n");}module_init(hello_init);//宏,指定模块加载时调用的函数module_exit(hello_exit);//宏,指定模块加载时调用的函数
关于MODULE_XXX宏做一个简单介绍:
MODULE_LICENSE<span style="white-space:pre"></span>//许可证,具体许可证内容自行百度MODULE_AUTHOR // 声明作者MODULE_DESCRIPTION //对这个模块作一个简单的描述,这个描述是"human-readable"的MODULE_VERSION // 这个模块的版本MODULE_ALIAS // 这个模块的别名MODULE_DEVICE_TABLE //告诉用户空间这个模块支持什么样的设备
编译、Makefile
前面我们已经写好了一个简单的hello模块,接下来要对模块进行编译。我们使用Makefile文件
# If KERNELRELEASE is defined, we've been invoked from the # kernel build system and can use its language. ifneq ($(KERNELRELEASE),) obj-m := hello.o # Otherwise we were called directly from the command # line; invoke the kernel build system. else KERNELDIR ?= /lib/modules/$(shell uname -r)/build #KERNELDIR赋值,指代内核源代码目录 PWD := $(shell pwd) #当前目录default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif
这是一个很有意思的Makefile脚本,当你在当前目录make的时候,它会执行两次。第一次执行的时候KERNELRELEASE未定义,因而会执行else分支的default目标的命令,即$(MAKE) -C $(KERNELDIR) M=$(PWD) modules .这条命令会进入内核源代码目录,执行内核源代码根目录下的Makefile,根目录下的Makefile会定义KERNELRELEASE,并切换到当前目录,再执行一遍当前目录的Makefile。此时KERNELRELEASE已被定义,因而会执行obj-m := hello.o 这条命令。从而整个依赖关系才完整,生成目标文件hello.ko。
ifeq ($(KERNELRELEASE),)目前,并无用处,它的由来是指在Linux源码根目录下的Makefile编译内核时,KERNELRELEASE宏会被定义,那么如果是从源码根目录开始的make则会将myhello.o模块编译进内核。
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 是Makefile的规则:这里的$(MAKE)就相当于make,-C 选项的作用是指将当前工作目录转移到你所指定的位置。“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成ko文件。模块加载:
编译好的模块hello.ko需要加载如内核才能使用。
sudo insmod XXX<span style="white-space:pre"></span>#加载模块sudo lsmod<span style="white-space:pre"></span>#查看已加载的所有模块sudo rmmod XXX<span style="white-space:pre"></span>#卸载模块而我们的prink输出会写入系统日志,可以通过dmesg查看。
因此我们的测试过程如下:
windeal@ubuntu:driver$ lsmod | grep hello #确认当前没有加载hello模块windeal@ubuntu:driver$ sudo insmod hello.ko #加载hello.ko模块windeal@ubuntu:driver$ dmesg<span style="white-space:pre"></span>#查看系统日志[190444.174802] Hello world!windeal@ubuntu:driver$ lsmod | grep hello<span style="white-space:pre"></span>#查看是否加载了hello模块hello 12449 0 windeal@ubuntu:driver$ sudo rmmod hello<span style="white-space:pre"></span>#卸载hello模块windeal@ubuntu:driver$ dmesg<span style="white-space:pre"></span>#查看系统日志[190444.174802] Hello world![190487.913667] Good bye, cruel world!windeal@ubuntu:driver$ lsmod | grep hello<span style="white-space:pre"></span>#查看模块是否被卸载了windeal@ubuntu:driver$
图:
- Linux驱动入门——构建和运行模块
- linux驱动入门——模块参数和导出符号
- Linux驱动入门——几个简单的Linux 模块
- Linux设备驱动之《构造和运行模块》
- 《Linux设备驱动》读书笔记:创建和运行模块(一)
- linux设备驱动学习(2) 构造和运行模块
- 【Linux 驱动】第二章 构造和运行模块
- linux设备驱动之构造和运行模块
- linux设备驱动第二篇:构造和运行模块
- linux设备驱动第二篇:构造和运行模块
- Linux驱动模块编写入门
- linux编写驱动模块入门
- linux 驱动开发-模块的构建
- Linux 驱动开发之内核模块开发 (二)—— 内核模块编译 Makefile 入门
- Linux 驱动开发之内核模块开发 (二)—— 内核模块编译 Makefile 入门
- linux驱动入门---test驱动模块加载
- linux 设备驱动程序 (2) —— 构造和运行模块
- 《Linux设备驱动程序》——构造和运行模块
- oracle学习笔记(3)_PL/SQL 和orcle服务
- String
- 威威猫系列故事——打地鼠
- 在Iframe中调用父子页面的js方法
- iOS5可能会删除本地文件储存
- Linux驱动入门——构建和运行模块
- Linq to sql :查询句法---orderby
- Ten Googol
- 小明系列故事——未知剩余系
- HDU 1535 Invitation Cards 有向图的来回最短路(邻接表反向建图)+spfa
- 第7章 函数
- 三足鼎立
- SQL Server 2008 R2 生成导出数据表的脚本
- 第9章 异常