模块编程属于内核编程,因此,除了对内核相关知识有所了解外,还需要了解与模块相关的知识。

1.应用程序与内核模块的比较

为了加深对内核模块的了解,表一给出应用程序与内核模块程序的比较。
表一 应用程序与内核模块程序的比较

从表一我们可以看出,内核模块程序不能调用libc库中的函数,它运行在内核空间,且只有超级用户可以对其运行。另外,模块程序必须通过module_init()和module-exit()函数来告诉内核“我来了”和“我走了”。

2.内核符号表

如之前所述,Linux内核是一个整体结构,像一个圆球,而模块是插入到内核中的插件。尽管内核不是一个可安装模块,但为了方便起见,Linux把内核也看作 一个“母”模块。
那么模块与模块之间如何进行交互呢?

一种常用的方法就是共享变量和函数

但并不是模块中的每个变量和函数都能被共享,内核只把各个模块中 主要的变量和函数放在一个特定的区段,这些变量和函数就统称为符号。到底哪些符号可以被共享? Linux内核有自己的规定。对于内核这个特殊的母模块,在kernel/ksyms.c中定义了从中可以“移出”的符号,例如进程管理子系统可以“移出”的符号定义如下:
/* 进程管理 */
EXPORT_SYMBOL(do_mmap_pgoff);
EXPORT_SYMBOL(do_munmap);
EXPORT_SYMBOL(do_brk);
EXPORT_SYMBOL(exit_mm);

EXPORT_SYMBOL(schedule);
EXPORT_SYMBOL(jiffies);
EXPORT_SYMBOL(xtime);


你可能对这些变量和函数已经很熟悉。其中宏定义EXPORT_SYMBOL()本身的含义是“移出符号”。为什么说是“移出”呢?因为这些符号本来是内核内部的符号,通过这个宏放在一个公开的地方,使得装入到内核中的其他模块可以引用它们。
实际上,仅仅知道这些符号的名字是不够的,还得知道它们在内核地址空间中的地址才有意义。因此,内核中定义了如下结构来描述模块的符号:
struct module_symbol
{
unsigned long value; /符号在内核地址空间中的地址/
const char *name; /符号名/
};
我们可以从/proc/ksyms文件中读取所有内核模块“移出”的符号,这所有符号就形成内核符号表,其格式如下:
内存地址 符号名 [所属模块]
在模块编程中,可以根据符号名从这个文件中检索出其对应的地址,然后直接访问该地址从而获得内核数据。第三列“所属模块”指符号所在的模块名,对于从内核这一母模块移出的符号,这一列为空。
模块加载后,2.4内核下可通过 /proc/ksyms、 2.6 内核下可通过/proc/kallsyms查看模块输出的内核符号

3.模块依赖

如前所述,内核符号表记录了所有模块可以访问的符号及相应的地址

当一个新的模块被装入内核后,它所声明的某些符号就会被登记到这个表(内核符号表)中,而这些符号可能被其他模块所引用,这就引出了模块依赖这个问题。

一个模块A引用另一个模块B所移出的符号,我们就说模块B被模块A引用,或者说模块A依赖模块B。如果要链接模块A,必须先链接模块B。这种模块间相互依赖的关系就叫模块依赖。

4.模块引用计数器

为了确保模块安全地卸载,每个模块都有一个引用计数器。

当执行模块所涉及操作时就递增计数器,在操作结束时就递减这个计数器;另外,当模块B被模块A引用时,模块B的引用计数就递增引用结束,计数器递减
什么时候可以卸载这个模块?当然只有这个计数器值为0的时候
例如,当一个文件系统还被安装在系统上 时就不能将其卸载,当这个文件系统不再被使用时,引用计数器就为0,于是可以卸载。

5 .模块编译

Linux 中最重要的软件开发工具是 GCC。
GCC 是 GNU 的 C 和 C++ 编译器。但是,在大型的开发项目中,通常有几十到上百个的源文件,如果每次均手工键入 gcc 命令进行编译的话,则会非常不方便。因此,人们通常利用make 工具来自动完成编译工作。利用这种自动编译可大大简化开发工作,避免不必要的重新编译。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。
编译工具make
实际上,make 工具通过一个称为 Makefile 的文件来完成并自动维护编译工作。Makefile 需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。下面给出2.6 内核模块的Makefile模板(请参看Makefile的写法)

Makefile2.6

obj-m += hellomod.o # 产生hellomod 模块的目标文件
CURRENT_PATH := $(shell pwd) #模块所在的当前路径
LINUX_KERNEL := KaTeX parse error: Expected 'EOF', got '#' at position 21: …l uname -r) #̲Linux内核源代码的当前版本…(LINUX_KERNEL) #Linux内核源代码的绝对路径
all:
make -C (LINUXKERNELPATH)M=(LINUX_KERNEL_PATH) M=(LINUXK​ERNELP​ATH)M=(CURRENT_PATH) modules #编译模块了
clean:
make -C (LINUXKERNELPATH)M=(LINUX_KERNEL_PATH) M=(LINUXK​ERNELP​ATH)M=(CURRENT_PATH) clean #清理
注意: 在每个命令前(例如make命令前)要键入一个制表符(按TAB键产生),在这里编者要啰嗦一句,一般第一次写的makefile会有一车的错误,下面贴上一篇总结了常见的错误的文章,希望能帮助到你。http://blog.csdn.net/sium__/article/details/48594871
有了Makefile,执行make命令,会自动形成相关的后缀为.o和.ko文件。
到此,模块编译好了,该把它插入到内核了:
如:$insmod hellomod.ko
当然,要以系统员的身份才能把模块插入。
成功插入后,可以通过dmesg命令查看,屏幕最后几行的输出就是你程序中输出的内容:Hello,World! from the kernel space…

当模块不再需要时,可以通过rmmod命令移去,例如
$rmmod hellomod

内核模块编程之入门(二)—必备知识相关推荐

  1. 库卡(KUKA)机器人入门学习必备知识

    库卡(KUKA)机器人入门学习必备知识 1.库卡机器人零点标定使用的工具通常有两种:1)千分表,标定精度偏低.2)EMD电子装置,标定精度较高. 2.库卡机器人停机模式有三种.分别是:STOP0,ST ...

  2. python 三引号_入门Python 必备知识基础(一)

    1 标识符 标识符是编程时使用的名字,用于给变量.函数.语句块等命名,Python 中标识符由字母.数字.下划线组成,不能以数字开头,区分大小写. 以下划线开头的标识符有特殊含义,单下划线开头的标识符 ...

  3. Torch的编程方式示例以及必备知识

    基于MNIST数据集通过torch实现一个简单的卷积神经网络,也可以用来验证torch是否安装成功 import torch import torchvision from torch.autogra ...

  4. 网络编程简单入门,基础知识需先掌握

    文章目录 网络编程入门 网络编程概述 网络编程三要素 ==IP地址== IP地址分类 通过控制台,获取IP的方法 InetAddress 三个常用方法 ==端口== 端口号 ==协议== UDP协议 ...

  5. C#(Sharp)GDI plus与图形编程(计算机图形学必备知识)

    文章目录 9.1 GDI+与图形编程 9.1.0 GDI概念 9.1.1 GDI+绘图命名空间 9.1.2 坐标系统 9.1.3 Graphics类 9.2 绘图工具类 9.2.1 Pen类 9.2. ...

  6. 零基础理解四元数,每个游戏入门开发必备知识

    废话不多说,直接进入正题 数学好的大佬直接看原文,此文基本照搬原文,加入了一点注解,公式比较清晰!!!!! 原文地址 复数 在我们能够完全理解四元数之前,我们必须先知道四元数是怎么来的.四元数的根源其 ...

  7. 网页编程从入门到精通 杨凡_学习计划丨西门子S7200编程从入门到精通

    点击关注? PLC进阶就上"技成PLC课堂"! S7-200从入门到精通这个课程涵盖了S7-200PLC的所有的功能应用,本视频主要分为以 下几个内容对S7-200PLC进行详细介 ...

  8. python编程入门必备知识-python基础教程#菜鸟也能看懂的超简单入门必备知识

    python基础语法教程 python一直是一门非常火爆的编程语言,从简洁的语法,全面的功能,也是得到许多编程萌新的重视,在刚刚接触编程不久的人来说,python就像是代码编程的入门语言,但其实想成为 ...

  9. 全站最全面的Python 基础入门必备知识大全,学完即就业!【建议收藏仔细学习】

    前言: Python作为21世纪最火的编程语言,市面上各种学习视频层出不穷,关于Python的学习氛围也逐渐浓厚!!最近一段时间越来越多的知友们在私信我,希望我出一期python基础入门的内容,肝了N ...

最新文章

  1. Ubuntu 18安装 chrome
  2. 1-3 数组的反序输出
  3. leetcode 7 Reverse Integer
  4. 面试必会系列 - 2.1 MySQL知识点大汇总(基本架构,存储引擎,锁,事务,索引,B+树等等)
  5. 【牛客 - 302哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(低年级)】小乐乐切割方块(思维,水题)
  6. Linux 安装 配置 Maven
  7. php 日志库,这可能是php世界中最好的日志库——monolog
  8. Python basemap模拟导弹发射
  9. SpringCloud整合Feign配置类之间的关系以及feign配置隔离的实现
  10. input 属性开启手机前置摄像头拍照
  11. 外语系列:英语翻译学习笔记
  12. spring boot 整合 ip2region(ip地址库)
  13. 大脑构造图与功能解析_大脑的结构和功能?
  14. python中key什么意思_Python中字典的key都可以是什么
  15. Ubuntu kylin 14.04下的spark1.0.1安装
  16. 强化学习入门系列一VS强化学习的基本概念
  17. Cartographe纯雷达计算位姿的前后端总结
  18. 记一次成功把Vue2后台项目改造成Vite2的踩坑经历
  19. QQ音乐推荐召回算法的探索与实践
  20. SWUST oj 254: 翻煎饼

热门文章

  1. oracle 怎么读取表结构和注释,生成数据库结构文档
  2. ubuntu下JDK的自动安装和手动安装
  3. JavaScript验证正则表达式大全
  4. 2.3Python基础语法(三)之输入输出
  5. 案例:java进制互转
  6. [C/C++标准库]_[0基础]_[怎样实现std::string自己的Format(sprintf)函数]
  7. POJ 3264 Balanced Lineup 【线段树】
  8. Programming Computer Vision with Python (学习笔记十二) 1
  9. 【翻译】针对多种设备定制Ext JS 5应用程序
  10. 信息学奥赛一本通 1965:【14NOIP普及组】珠心算测验 | 洛谷 P2141 [NOIP2014 普及组] 珠心算测验