系列文章目录

linux学习笔记(五)编译内核模块生成ko驱动文件


文章目录

  • 系列文章目录
  • 前言
  • 一、加载内核简介
  • 二、第一个hello world文件
    • 1.文件树
    • 2.hello.c
    • 3.Makefile
  • 三 编译命令
  • 总结
    • 互相交流

前言

系统:ubuntu 1604
功能:加载内核模块


提示:以下是本篇文章正文内容,下面案例可供参考

一、加载内核简介

Linux内核的整体架构本就非常庞大,其包含的组件也非常多。而我们怎样把需要的部分都包含在内核中呢?一种方法是把所有需要的功能都编译到Linux内核中。这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,将不得不重新编译内核。

Linux提供了这样的机制,这种机制被称为模块(Module)。可使得编译出的内核本身并不需要包含所有功能,而在这些功能需要被使用的时候,其对应的代码被动态地加载到内核中。
模块本身不被编译入内核映像,从而控制了内核的大小。·模块一旦被加载,它就和内核中的其他部分完全一样。
这篇文章提供了最简单的一个内核模块工程,第一个hello world工程。

而且是单独编译到内核中,方便安装和删除。

二、第一个hello world文件

1.文件树

├── hello.c├── Makefile

整个工程只有两个文件,一个hello.c,一个用来控制编译的Makefile。

2.hello.c

代码如下(示例):


#include <linux/init.h>
#include <linux/module.h>static int __init hello_init(void)
{printk(KERN_INFO "Hello World enter\n");return 0;
}
module_init(hello_init);static void __exit hello_exit(void)
{printk(KERN_INFO "Hello World exit\n ");
}
module_exit(hello_exit);MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple Hello World Module");
MODULE_ALIAS("a simplest module");

代码解析:
内核模块中用于输出的函数是内核空间的printk()而不是用户空间的printf(),printk()的用法和printf()基本相似,但前者可定义输出级别。printk()可作为一种最基本的内核调试手段。

一个Linux内核模块主要由如下几个部分组成。
(1)模块加载函数
当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。
Linux内核模块加载函数一般以__init标识声明,模块加载函数以“module_init(函数名)”的形式被指定。它返回整型值,若初始化成功,应返回0。而在初始化失败时,应该返回错误编码。在Linux内核里,错误编码是一个接近于0的负值。
(2)模块卸载函数
当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块卸载函数相反的功能。
Linux内核模块加载函数一般以__exit标识声明,模块卸载函数在模块卸载的时候执行,而不返回任何值,且必须以“module_exit(函数名)”的形式来指定。
(3)模块许可证声明许可证(LICENSE)
声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(Kernel Tainted)的警告。在Linux内核模块领域,可接受的LICENSE包括“GPL”、“GPL v2”、“GPLand additional rights”、“Dual BSD/GPL”、“Dual MPL/GPL”和“Proprietary”(关于模块是否可以采用非GPL许可权,如“Proprietary”,这个在学术界和法律界都有争议)。大多数情况下,内核模块应遵循GPL兼容许可权。Linux内核模块最常见的是以MODULE_LICENSE(“GPL v2”)语句声明模块采用GPL v2。
(4)模块参数(可选)
模块参数是模块被加载的时候可以传递给它的值,它本身对应模块内部的全局变量。
(5)模块导出符号(可选)
内核模块可以导出的符号(symbol,对应于函数或变量),若导出,其他模块则可以使用本模块中的变量或函数。
(6)模块作者等信息声明(可选)

MODULE_AUTHOR、MODULE_DESCRIPTION、MODULE_VERSION、MODULE_DEVICE_TABLE、MODULE_ALIAS分别声明模块的作者、描述、版本、设备表和别名
(7)printk
printk的日志级别定义如下(在include/linux/kernel.h中):

#define KERN_EMERG 0#define KERN_ALERT 1#define KERN_CRIT 2#define KERN_ERR 3#define KERN_WARNING 4#define KERN_NOTICE 5#define KERN_INFO 6#define KERN_DEBUG 7

3.Makefile

KVERS = $(shell uname -r)
#shell中输出uname -r会获得内核版本号,这里将版本号存到变量KVERS
# Kernel modules
#将后面的东东编译为“内核模块”, obj-y 编译进内核,obj-n 不编译。
obj-m += hello.o# 开启EXTRA_CFLAGS=-g-O0,可以得到包含调试信息的hello.ko模块。
#EXTRA_CFLAGS=-g -O0
#-C 表示让 make 命令进入指定的内核源代码目录
build: kernel_modules
kernel_modules:make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modulesclean:make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

:=”表示:它的右边如果为变量,那么该变量在这条语句之前就要定义好,而不能在使用这条语句之后定义的变量
“=”表示:当它右边如果变量时,这个变量可以在这条语句之前或者之后使用
“?=”表示:当它左边的变量在这条语句之前没有定义过,则执行本条语句,如果已经定义了,则什么都不做。

三 编译命令

make
#make的提示信息中,CC是编译,LD是链接
modinfo hello.ko#获得模块的信息
sudo insmod hello.ko #或者是insmod ./hello.ko
#加载时输出“Hello World enter”
lsmod #获得系统中已加载的所有模块以及模块间的依赖关系
sudo rmmod hello
#卸载时输出“Hello World exit”。
lsmod #获得系统中已加载的所有模块以及模块间的依赖关系

总结

以上代码,在lsmod中确实可以看到能够加载内核模块 ,但是不知道为什么无法打印输出信息。改了printk的输出级别也不管用。有网友知道的可以告诉我。

互相交流

读者你好!如果你对本文内容感兴趣,我十分希望能够和你互相学习,可以扫码和我联系!一起进步

linux学习笔记(五)编译内核模块生成ko驱动文件相关推荐

  1. 编译内核模块生成ko驱动文件

    1.加载内核简介 Linux内核的整体架构本就非常庞大,其包含的组件也非常多.而我们怎样把需要的部分都包含在内核中呢?一种方法是把所有需要的功能都编译到Linux内核中.这会导致两个问题,一是生成的内 ...

  2. Linux学习笔记-动态库的生成

    库分为两种: (1)共享库 Shared Library  (2)静态库 Static Library 通常共享库也称为动态库. 使用g++命令来生成动态库编译,生成.o文件 (编译选项 ‐fPIC  ...

  3. Linux学习笔记五:arm-2009q3交叉编译环境安装、U盘拷贝文件到开发板

    目录 一.概述 二.arm-2009q3安装 三.编译测试 四.开发板运行 一.概述 现在已经完成PC端的虚拟机环境安装.完成了开发板镜像烧写.以测试的hello为例,PC端使用gcc hello.c ...

  4. Linux学习笔记---初次编译Uboot系统

    在初次编译Uboot系统时,是按照正点原子开发指南操作的,但是开发指南上讲得不是很详细,又看了一遍视频教程才搞清楚完整步骤,为了方便学习,就将详细步骤记录下来,以便以后参考. Uboot初次编译 1. ...

  5. v8学习笔记(五) 编译过程

    v8编译过程(parser.cc文件) 1.创建编译环境MakeAST() 解析器AstBuildingParser parser->扫描器Scanner scanner_ 扫描器结构: (1) ...

  6. 写得蛮好的linux学习笔记五-认识SHELL(收藏)

    认识SHELL alias    显示当前所有的命令别名      alias lm="ls -al"   命令别名    unalias lm 取消命令别名 type      ...

  7. linux发指令给网络设备,Linux学习笔记五(网络命令)

    1. 给用户发信息命令:write 指令名称:write 指令所在路径:/usr/bin/write 执行权限:所有用户 语法:write 功能描述:给用户发信息,以Ctrl+D保存结束 范例: # ...

  8. Linux学习笔记(三)文本相关,文件权限,vim

    文章目录 cat 显示文本 tac 倒序显示 less 分屏显示文本 more 分页显示文件 head 显示文件的前面的内容 tail 显示文件的后面的内容 cut 切割 paste 合并 wc 用来 ...

  9. Linux 学习笔记(一)如何安装.bin文件

    1.如何安装.bin文件 如果你有root权限,那么./a.bin 即可,如果没有该权限,则chmod +x a.bin 2.如何创建文件夹 mkdir XXX文件夹名 3.如何删除文件夹 rm -r ...

最新文章

  1. WP7基础---补充
  2. java 字符串拼接优化_JAVA字符串拼接效率
  3. HDU5692(线段树+dfs序)
  4. Daily Scrum M2 10-29
  5. 电压放大倍数公式运放_运放电路:同相放大还是反相放大?
  6. Netcraft :2019年4月全球Web服务器排名 nginx首度登顶
  7. 计算机组成原理实验串行口,计算机组成原理实验2.ppt
  8. html链接sqlserver,js连接sqlserver进行查询
  9. SQL2005 远程连接问题解决方法
  10. IntelliJ IDEA使用技巧(一)——常用快捷键
  11. glibc中malloc源码分析
  12. golang做php的中间件,Golang 之 中间件
  13. BilSTM 实体识别_肿瘤新抗原(neoantigen)专题八:新抗原识别策略使难治性实体瘤的个体化免疫治疗成为可能...
  14. 数据保护与云不离不弃,云中护航渐成行业主旋律
  15. [146]PyUserInput模拟鼠标和键盘模拟
  16. C# 定时服务之Hangfire使用、与Quartz的对比
  17. (纯前台)读取、解析并展示xls/xlsx
  18. 【JS篇】禁止手机默认键盘弹出
  19. fgsea进行GSEA富集分析
  20. 计算机画图设计前景色,画图的前景色和背景色

热门文章

  1. HutoolUtil
  2. 3·15报道:“隔空盗刷”资金骗局曝出
  3. 中专计算机寒假作业,中职计算机寒假作业[优质课资]
  4. TIA博途下载PLC程序时提示“具有激活的TIS功能防止下载到设备”错误-处理办法
  5. CDH-distcp
  6. WmiPrvSE.exe 长时间占用CPU
  7. 微信小程序日历包含(阴历)- - -附效果图
  8. Cisco路由器配置教程
  9. 【React Native】集成声网Agora语音通讯
  10. Python3的四舍五入round()函数