linux驱动程序开发的详细介绍

linux驱动程序开发的详细介绍
注释:前提是,一般来说,内核代码错误可能导致用户进程的死亡,或者整个系统瘫痪。更严重的后果可能导致磁盘损坏。因此,最好有一台试验机进行系统测试。

前提,一般来说,内核代码错误可能导致用户进程的死亡,或者整个系统的瘫痪。更严重的后果可能导致磁盘损坏。因此,最好有一台试验机进行系统测试。
第一个内核模块(Hello World模块)

复制代码代码如下所示:
查看代码
#包括
#包括
module_license(双BSD和GPL );
静态__init int hello_init(void)
{
/ / printk函数在内核模块中定义,和内核需要自己多打印涵洞
因为它依赖于自己的操作,没有相应的库函数。
/ /模块insmod加载后调用printk,模块与内核
因为一些可以调用内核/公共符号,kern_alert是消息的优先级
printk(kern_alert 你好世界;
返回0;
}
静态__exit虚空(void)hello_exit
{
printk(kern_alert 再见);
}
module_init(hello_init);
module_exit(hello_exit);

在模块中定义的两个功能,一个模块加载到内核调用(hello_init),另一个在内核将从调用模块删除(hello_exit);在上面的代码中,module_init和module_exit两核宏,用来告诉内核从哪里开始,在哪里退出module_license宏模块用于声明以下免费许可,否则内核加载会出现警告。
好了,现在我们可以对上面的程序进行相应的测试了。在测试之前,我们已经编制了相应的makefile文件。模块的编译不同于普通程序的编译。
makefile文件

复制代码代码如下所示:
查看代码
# makefile为你好世界
# kernelrelease是内核源代码定义的第一个变量
Ifneq($(kernelrelease),#)判断变量是否为空(第一次执行未定义)
执行else语句不确定时#
obj-m:= HelloWorld。O #表明有一个模块被设置从目录文件HelloWorld。O,然后将设置
#名叫HelloWorld.ko
#如果有一个模块被称为module.ko,来自两个源文件file1 file2。C和C的假设。
#应该是:obj-m = O模块。
#模块对象:file1 file2 O O =。。
其他的
可得:= / / /美元库模块(壳uname -r) /建造
所有:
#当目标是,C $(可得)跳到内核源码目录读取makefile
# M = $(PWD)方法返回当前目录,继续阅读,当前执行的makefile,当再次执行
# $(kernelrelease)已经被定义,将之前的阅读其他内容
让C $(可得)M = $(PWD)模块
清洁:
rm -rf *。柯*。* MOD。O * MOD。symvers C *。
endif

相应的解释如上面所述。
作为一个编译内核:它必须是一个超级用户
在当前路径下输入
在编译完成后,进入insmd helloworld.ko加载内核,并使用dmesg |尾看到内核的输出信息。
使用rmmod的dmesg |尾看到打印出再见的使用相应的HelloWorld去核
printk不得出口到屏幕上,这是对kern_alert优先级相关,这还不够高。内核输出的内容可以在/ var /日志/ kern.log查看,并可以通过vim / / / kern.log VaR日志查看。
内核模块不同于应用程序。
1:应用程序运行后,相应的任务将被处理。在内核模块注册,它是用来满足未来的要求,并增加了__init初始化函数后,调用完成后,将立即释放内存空间。
2:当应用程序终止时,它不负责资源的恢复,并且由操作系统维护,但是内核模块在移除资源时必须释放资源。
3:应用程序可以调用相应的库函数,而内核模块只能调用内核中输入的函数。在内核模块编程中,源文件不应包含通常的头文件,但也有例外情况,如少数头文件的唯一例外。
4:处理错误的方式是不同的。在应用程序的中间部分,可以通过相应的调试器检查和修改错误,但在内核模块中,如果不终止整个系统,段错误将终止当前进程。
用户空间和内核空间:
应用程序在用户空间中运行,内核模块在内核空间运行,每个模式都有自己的内存映射,以及自己的地址空间。
内核与当前进程的关系:
内核模块所做的大部分操作代表一个特定的过程,内核代码可以通过访问全局项目流来引用当前进程,这被定义为:
#定义当前(get_current) /通过宏定义可以获得一个指针,指针的任务task_struct
内核代码可以使用当前流来使用特定于流程的信息。
内核符号表:
内核模块在加载时通过查找内核符号表来解决未定义的符号,内核符号表包含全局内核项的地址。加载模块时,模块中导出的符号也将成为内核符号表的一部分。
模块的输入符号通常使用以下两种形式:
export_symbol(名称)
export_symbol_gpl(名称)
以上宏定义使给定符号以外的模块使用,对_gpl版宏定义可以使符号可用的_gpl许可模块。
版本依赖:
该模块的代码都必须重新编译为每个连接到内核版本,在编写模块的过程中,第一步是阅读Makefile文件的内核,在编译内核树文件的过程(vermagic。O)连接到你的模块,在内核中的文件有很多相关的信息,包括版本…
模块参数:
模块参数指定用insmod和modprobe加载时。
到以前的HelloWorld的变化。C如下:
终端输入

复制代码代码如下所示:
使
Insmod HelloWorld.ko = test num = 10;
dmesg |尾3

你可以看到它。
使用module_param_array(名称、类型、数量、烫发)在声明数组参数
名称是数组的名称,类型是数组元素的类型,Num是无数个数组的数组,烫发是权限。
附录:insmod
insmod内核模块加载到内存中,它依赖于一个定义在内核/模块。C的系统调用sys_init_module函数分配内核内存来存储模块,然后复制模块代码的内存区域,使用内核符号表解决内核引用模块,和初始呼叫功能启动所有模块。什么.
的modprobe工具也被用来加载内核模块来记忆。不像insmod,它会在加载模块,看看它是否已经在当前的内核引用未定义的符号。如果有,它会在当前的搜索路径模块是否定义了该符号,如果是这样,该模块加载到内核。
rmmod用于去除内核模块,如果内核认为模块仍然在使用,或如果内核配置为不允许模块被删除,该模块的卸载会失败。
lsmod体现所有模块加载到当前的系统列表。
内核模块编程中的函数通常声明为静态的,因为它们在文件外是不可见的。

tag:程序开发详细介绍电脑软件Linux

相关内容