Linux运行时分为用户空间和内核空间两个部分。这个有点儿现在的体制内和体制外的区别,同时运行,但是运行的环境和所使用的规则不一样。用户空间运行的叫程序(APP),都有个main接口,内核空间运行的程序叫模块(module)。
任何程序的开始都有一个hello world。当然先show 一个用户空间hello world 。以下都是C语言实现的。
#include <stdio.h>
int main()
{
printf(“hello world!\n”);
return 0;
}
从上面的应用程序我们可以看到,一个C语言用户空间的程序都会有一个入口。 Main 函数、同时出口在main 函数内return 0;(void 类型是return ; 默认包含)、当然它还默认包含了运行这个函数所需要的库。
编译它很简单
gcc hello.c -o test.out
它之所以这个简单是因为系统默认做好了一系列的准备工作。并且包含了一些默认的选项。这些准备工作包含,gcc 默认连接glibc 库,stdio.h也包含在gcc 默认的包含的include目录中。
从http://blog.csdn.net/aero_boy/article/details/1539040 中摘录一段代码,
引用开始
1.第一个模块
下面是一个简单的hello world的内核模块,从中我们可能了解基本的内核模块开发方法。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_init( void ){
printk(KERN_ALERT "Hello World ! " );
return 0;
}
static void __exit hello_exit(void){
printk(KERN_ALERT "Goodbye! ");
}
module_init( hello_init);
module_exit( hello_exit);
MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "MyName" );
这个简单的程序以包含了模块的主要特征,每个模块都有一个入口和出口,在这个程序中是hello_init()和hello_exit(),它们分别通过module_init()和module_exit()系统调用注册到内核中,内核在加载这个模块时,调用hello_init()函数,在这个函数中一般做一些初始化工作,如果初始化顺利完成,返回零,否则返回一个非零值。hello_exit()是模块的出口函数,内核在卸载该模块是调用,负责释放资源等。
MODULE_LICENSE用于指定版权,linux一般使用"GPL"。
MODULE_AUTHOR用于指定代码的工作。
2.构建模块
在2.6内核中,使用新的"kbuild"构建系统,使构建模块更加容易了。我们写的模块可以单独放在一个我们自己的目录中,以可能直接放到源代码做中,下面是一个单独使用的Makefile
obj-m := hello.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD)
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
引用结束。
上面的过程十分的清晰明了,按照以上过程做的话基本上不会出什么问题。But,基本上并不代表全部,很多人发现做的时候发现,/lib/modules/$(shell uname -r)/build 根本就不存在啊。。总么办呢。
用户空间讲过之所以他的编译这么简单是因为系统已经做好准备工作了。其实原因很简单因为linux很多安装软件的方式都是通过编译安装。So。。不做好准备工作,估计都没得人用了。
下面将介绍内核编译的准备工作:
建立内核源码树;
1.下载源码。百度 kernel 第一个就是下载(建议解压到一个不会被删除的目录中)。
2.配置源码。生成 .config 一般在/boot 目录下可以找到 config-xx的文件(mv config-xxx 到linux kernel目录下)
3.Make 运气好的话等个1-2小时。运气不好编译出错,就google解决了哦。
4.Make modules
5.Make modules_install
额。到这里基本上按照教程所指导的就可以完成编译操作了。其实原理网上文章都讲得差不多。对于刚入门的新人来说只需要知道:
module_init( hello_init);
module_exit( hello_exit);
一个是加载模块时调用hello_init。类似C++中的构造函数。
一个是模块卸载的时候调用hello_init,类似于C++中的析构函数。
加载模块使用的是insmod 或者 modprobe 对于它有什么区别后续文章会有讲到。其实google一下你就知道了。
卸载模块的时候使用的是 rmmod 。
查看当前模块是否加载上使用的是lsmod。
查看printk的输出:可以使用dmesg 即可。
至于两个函数的类型,照着copy就行了。初学者,越简单越好,就不要去问为啥了。就好比为啥main函数的返回值就是个int 呢、、、