-
应用程序。库,内核,驱动程序关系
简单的理解就是平时我们在操作系统(内核)上写的代码叫做应用程序,我们会调用一些库函数/编译生成的链接文件(如xxx.so),这些统称为库。而它们运行在“用户空间”,区分出用户空间是为了操作系统的正常运行,防止写的程序对内存的操作导致系统崩溃,可能你的系统再也跑步起来了,只能重装。而驱动程序往往会加载进内核,告诉内核我会干什么事,有需要可以叫我。而每个驱动程序又叫模块,模块的加载与卸载又分为以下两种情况。
-
驱动程序的加载与卸载
驱动程序的使用有两种办法:
(1)静态编译进内核,和内核一块运行。用起来的感受就是,电脑开机,这个驱动就可用了,比如网卡模块。
(2)作为模块在使用时加载。一种是手动:也就是通过insmod和rmmod来加载卸载模块。另一种就是唤醒 ,比如插入串口模块,串口的驱动就被加载并使用。
-
简单的动态加载实例
- 首先创建如上图的文件,然后helloworld.c文件内容如下
#include <linux/module.h>
#include <linux/kernel.h>
int init_hello_module(void)
{
printk("***************Start***************\n");
printk("Hello World! Start of hello world module!\n");
return 0;
}
void exit_hello_module(void)
{
printk("***************End***************\n");
printk("Hello World! End of hello world module!\n");
}
MODULE_LICENSE("Dual BSD/GPL");
module_init(init_hello_module); //加载模块执行的函数init_hello_module
module_exit(exit_hello_module); //卸载模块执行的函数exit_hello_module
- makefile文件的代码----然后make生成helloworld.ko文件-----在通过insmod helloworld.ko即可加载模块
obj-m := helloworld.o #生成helloworld.o文件
CROSS_COMPILE =
CC = gcc
KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)
PWD := $(shell pwd) #shell脚本执行pwd,得知当前位置
all: modules
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend *.symvers .*.cmd *.ko *.mod.c .tmp_versions $(TARGET)
lsmod | 查看已加载所有模块 |
lsmod | grep helloworld | 查看已加载的名为helloworld的模块 |
insmod xxx.ko | 加载模块 xxx.ko |
rmod xxx | 卸载模块 |
但此时需要查看加载模块打印的字符啊!!于是在终端输入 dmesg 即可看到初始化的打印。。
-
module_param()函数可在加载模块的时候输入参数,类似于int main(char argc, char **argv)函数,在执行时加入参数即可使用。
#include <linux/module.h>
#include <linux/kernel.h>
static char *book_name = "dissecting Linux Device Driver";
static int num = 4000;
int init_hello_module(void)
{
printk("***************Start***************\n");
printk("Hello World! Start of hello world module!\n");
printk(KERN_INFO "book name: %s \n",book_name);
printk(KERN_INFO "book num: %d \n",num);
return 0;
}
void exit_hello_module(void)
{
printk("***************End***************\n");
printk("Hello World! End of hello world module!\n");
printk(KERN_INFO " book num:%d\n",num);
}
module_init(init_hello_module); //加载模块执行的函数init_hello_module
module_exit(exit_hello_module); //卸载模块执行的函数exit_hello_module
//module_param(参数名,参数类型,参数读/写权限);
//在模块被编译时会将 module_param 中声明的类型与变量定义的类型进行比较,判断是否一致。
module_param(num,int,S_IRUGO); //定义一个int类型的num参数,权限为S_IRUGO。
module_param(book_name, charp, S_IRUGO); //定义一个char*类型的book_name参数,权限为S_IRUGO.
MODULE_LICENSE("Dual BSD/GPL");
sudo insmod helloworld.ko book_name='GoodBook' num=5000,用dmesg查看打印使用输入的参数。'GoodBook'和5000
sudo insmod helloworld.ko用dmesg查看打印使用默认参数"dissecting Linux Device Driver" 和4000