Linux内核驱动学习之HelloWorld内核模块!

转载自

(1)https://blog.csdn.net/sh21_/article/details/60878812?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

(2)https://www.cnblogs.com/wangyuezhuiyi/archive/2011/11/15/2250102.html

(3)https://blog.csdn.net/u010632165/article/details/86541941?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight 


内核模块基本原理:

内核模块是可以根据实际需要可以动态加载和卸载到内核中的代码。它们扩展了内核的功能,而无需重启系统,就可以进行模块加载,并工作。

Linux 内核模块(LKM)是可以根据实际需要可以动态加载和卸载到内核中的代码。它们扩展了操作系统内核功能却不需要重新编译内核、启动系统。如果没有内核模块,就不得不反复编译生成操作系统的内核镜像来加入新功能,当附加的功能很多时,还会使内核变得臃肿。一个Linux 内核模块主要由以下几个部分组成:

(1) 模块加载函数(必须):当通过insmod 或modprobe 命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块相关初始化工作。

(2) 模块卸载函数(必须):当通过rmmod 命令卸载模块时,模块的卸载函数会自动被内核执行,完成与模块加载函数相反的功能。

(3) 模块许可证声明(必须):模块许可证(LICENCE)声明描述内核模块的许可权限,如果不声明LICENCE,模块被加载时将收到内核被污染的警告。大多数情况下,内核模块应遵循GPL 兼容许可权。Linux2.6 内核模块最常见的是以MODULE_LICENSE(“Dual BSD/GPL”)语句声明模块采用BSD/GPL 双LICENSE。

(4) 模块参数(可选):模块参数是模块被加载的时候可以被传递给他的值,它本身对应模块内部的全局变量。

(5) 模块导出符号(可选):内核模块可以导出符号(symbol,对应于函数或变量),这样其他模块可以使用本模块中的变量或函数。

(6) 模块作者等信息声明(可选)。

一个内核模块至少包含两个函数,模块被加载时执行的初始化函数init_module()和模块被卸载时执行的结束函数cleanup_module()。在最新内核稳定版本2.6 中,两个函数可以起任意的名字,通过宏module_init()和module_exit()注册调用要编译内核模块,把代码嵌进内核空间,首先要获取内核源代码,且版本必需与当前正在运行的版本一致。



helloworld.c

helloworld.c

(1) moudle.h 包含了大量加载模块需要的函数和符号的定义.

(2) init.h 来指定你的初始化和清理函数

(3) MODULE_LICENSE("GPL");指定代码使用哪个许可

           内核认识的特定许可有, 

                "GPL"( 适用 GNU 通用公共许可的任何版本 ), 

                "GPL v2"( 只适用 GPL 版本 2 ), 

                "GPL and additional rights", 

                "Dual BSD/GPL", 

                "Dual MPL/GPL", 

                "Proprietary".

(4) 除此之外还可以包含模块的其他描述性定义

          MODULE_AUTHOR ( 声明谁编写了模块 ), 

          MODULE_DESCRIPION( 一个人可读的关于模块做什么的声明 ), MODULE_VERSION ( 一个代码修订版本号),

          MODULE_ALIAS ( 模块为人所知的另一个名子 ), 

          MODULE_DEVICE_TABLE ( 来告知用户空间, 模块支持那些设备).

(5) static int hello_init(void)

             初始化函数应当声明成静态的,

          static void hello_exit(void) 

               清理函数, 它注销接口, 在模块被去除之前返回所有资源给系统

(6) module_init(hello_init);

           这个宏定义增加了特别的段到模块目标代码中, 表明在哪里找到模块的初始化函数. 没有这个定义, 你的初始化函数不会被调用.

           module_exit(hello_exit);

(7)printk

            在 Linux 内核中定义并且对模块可用; 它与标准 C 库函数 printf 的行为相似. 内核需要它自己的打印函数, 因为它靠自己运行

(8)字串 KERN_ALERT 是消息的优先级,因为使用缺省优先级的消息可能不会在任何有用的地方显示

Makefile

Makefile

(1)obj-m := hello.o

              表明有一个模块要从目标文件 hello.o 建立. 在从目标文件建立后结果模块命名为 hello.ko。

(2)KernelDIr := /lib/modules/$(shell uname -r)/build/

              用来定位内核源码目录

(3)PWD := $(shell pwd)

             获得当前目录路径

(4)M=$(PWD) M= 选项

              使 makefile 在试图建立模块目标前, 回到你的模块源码目录

(5)$(MAKE) -C $(KERNELDR) M=$(PWD) modules

              这个命令开始是改变它的目录到用 -C 选项提供的目录下( 就是说, 你的内核源码目录 ). 它在那里会发现内核的顶层 makefile. 这个 M= 选项使 makefile 在试图建立模块目标前, 回到你的模块源码目录. 这个目标, 依次地, 是指在 obj-m 变量中发现的模块列表, 在我们的例子里设成了 module.o.

(6)$(MAKE) -C $(KERNELDR) M=$(PWD) modules_install

             用于模块的安装

(7)rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

             用于make clean清除上次编译生成的文件


模块加载、查看、卸载

insmod   helloworld.ko   #将编译生成的ko文件加载到内核中

lsmod | grep helloworld #查看内核模块是否有helloword

rmmod   helloworld.ko   #删除内核中的ko模块

模块调试:

dmesg | grep "init success" # 在终端查看init函数中,KERN——INFO的打印信息

dmesg | grep "exit success" # 在终端查看exit函数中,KERN——INFO的打印信息

dmesg  #查看内存缓冲区的内容

dmesg | tail -12   #查看内核输出信息,tail -12 显示最后12条;

dmesg | grep word_count |tail -n 2

cat /var/log/syslog | grep word_count |tail -n 2

modinfo  模块名.ko  #查看模块路径、协议、作者等信息


echo  'la zi ji' > /dev/wordcount  #向设备文件写数据

dmesg 


初次编写时出现的问题:

1. 卸载函数exit的返回值必须为void;

2. $(MAKE) -C $(KERNELDIR) M=$(PWD) 后面只能是modules 或空

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342