linux内核模块编程入门 2013-07-06 23:59:54

分类: LINUX

原文地址:linux内核模块编程入门 作者:s270768095

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

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

  C语言应用程序 内核模块程序
使用函数 Libc库 内核函数
运行空间 用户空间 内核空间
运行权限 普通用户 超级用户
入口函数 main() module_init()
出口函数 exit() module_exit()
编译 Gcc –c Makefile
连接 Gcc insmod
运行 直接运行 insmod
调试 Gdb kdbug, kdb,kgdb等

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

2.内核符号表(如果对以下第2~4点理解上有困难,可以越过)

前所述,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,于是可以卸载。

四.模块编译

Linux 中最重要的软件开发工具是 GCC。GCC 是 GNU 的 C 和 C++ 编译器。但是,在大型的开发项目中,通常有几十到上百个的源文件,如果每次均手工键入 gcc 命令进行编译的话,则会非常不方便。因此,人们通常利用 make 工具来自动完成编译工作。利用这种自动编译可大大简化开发工作,避免不必要的重新编译。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。

1.编译工具make

实际上,make 工具通过一个称为 Makefile 的文件来完成并自动维护编译工作。Makefile 需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。下面给出2.6 内核模块的Makefile模板(请参看Makefile的写法)

# Makefile2.6
obj-m += hellomod.o        # 产生hellomod 模块的目标文件
CURRENT_PATH := $(shell pwd)   #模块所在的当前路径
LINUX_KERNEL := $(shell uname -r)    #Linux内核源代码的当前版本
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL) #Linux内核源代码的绝对路径
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules   #编译模块了
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean    #清理

注意: 在每个命令前(例如make命令前)要键入一个制表符(按TAB键产生)

有了Makefile,执行make命令,会自动形成相关的后缀为.o和.ko文件。
到此,模块编译好了,该把它插入到内核了:
如:$insmod hellomod.ko

当然,要以系统员的身份才能把模块插入。

成功插入后,可以通过dmesg命令查看,屏幕最后几行的输出就是你程序中输出的内容:Hello,World! from the kernel space…

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

$rmmod hellomod

http://blog.chinaunix.net/uid-14811365-id-3790826.html

inux内核模块编程入门的更多相关文章

  1. 转inux Shell编程入门

    http://www.cnblogs.com/suyang/archive/2008/05/18/1201990.html 从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来 ...

  2. 脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

    .引言 网络编程中TCP协议的三次握手和四次挥手的问题,在面试中是最为常见的知识点之一.很多读者都知道“三次”和“四次”,但是如果问深入一点,他们往往都无法作出准确回答. 本篇文章尝试使用动画图片的方 ...

  3. [转帖]脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

    脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手   http://www.52im.net/thread-1729-1-1.html     1.引言 网络编程中TCP协议的三次握手和 ...

  4. PHP面向对象(OOP)编程入门教程

    面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...

  5. Windows编程入门程序详解

    引用:http://blog.csdn.net/jarvischu/article/details/8115390 1.     程序 /******************************* ...

  6. 【PHP面向对象(OOP)编程入门教程】1.什么是面向对象?

    面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成 ...

  7. Linux 利器- Python 脚本编程入门(一)

    导读 众所周知,系统管理员需要精通一门脚本语言,而且招聘机构列出的职位需求上也会这么写.大多数人会认为 Bash (或者其他的 shell 语言)用起来很方便,但一些强大的语言(比如 Python)会 ...

  8. 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)   介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...

  9. OpenAl编程入门:播放一段音频

    OpenAl编程入门 关于OpenAl我就不多介绍了,这两篇说明对于初步了解已经足够了:http://baike.baidu.com/view/1355367.htmhttp://en.wikiped ...

随机推荐

  1. Java——Spring注解

    Spring常用注解使用注解来构造IoC容器用注解来向Spring容器注册Bean.需要在applicationContext.xml中注册<context:component-scan bas ...

  2. java web项目和java项目的区别(看清IDE本质)

    想必大家在使用MyEclipse时对这两个概念不去深究.只知道是Java EE类的基本都是Web项目,而Java应用程序就是Java项目.而且很多人都愿意使用MyEclipse作为开发工具,且不说大家 ...

  3. XML在线转化为JSON

    http://www.utilities-online.info/xmltojson/

  4. css nth-child 的应用

    最近改视频监控页面,由于窗口比较多,以前是通过计算窗口大小位置来处理页面布局的,其实还是比较麻烦,而且偶尔会有页面位置错乱的现象,虽然只是及其偶尔的现象,但总归是不好. 计算窗口位置的代码: /*监控 ...

  5. Redis 之sentinel运维监控

    有三台redis服务器6379.6380.6381,配置6379为主服务器,6380与6381都为6379的从服务器.如果主服务器6379挂掉了,我们怎么办? 方式一:手动修改从服务器的配置,将638 ...

  6. 网络爬虫 robots协议 robots.txt

    网络爬虫 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成.传统爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上 ...

  7. mysql cpu 100% 满 优化方案 解决MySQL CPU占用100%的经验总结

    下面是一些经验 供参考 解决MySQL CPU占用100%的经验总结 - karl_han的专栏 - CSDN博客 https://blog.csdn.net/karl_han/article/det ...

  8. enote笔记语言(4)

    what:我想知道某个“关键词(keyword)”(即,词语,可以是概念|专业术语|.......)的定义. why:我想知道事物发生的原因:我会不会犯“归因错误”?是“单因素”的还是“多因素”的原因 ...

  9. 如何在redhat 7上安装VNC服务器

    平时我们基本上都是用xshell或者用putty远程我们的linux服务器,如果我们的linux服务器安装了图型化界面那我们又该如何远程使用我们的图形化界面呢?下面我们用vnc来实现远程我们的linu ...

  10. gitlab的添加密钥

    1.在本地电脑下载git的客户端并且安装 2.鼠标右键左面选中Git Bash Here 3.操作如下图生成密钥 4.将密钥复制过来添加到gitLab中 5.Eclipse配置密钥 6.在git创建的 ...