说是要2.6内核的源码书,所以就去kernel.org下载一个2.6的内核linux-2.6.32.63.tar.xz
xz -d linux-2.6.32.63.tar.xz
tar -xvf linux-2.6.32.63.tar
cd linux-2.6.32.63
make oldconfig #配置原版
make -j4 @编译内核(此过程耗时长,编译完后在linux-2.6.32.63多出一个vmlinux,jN代表用几个线程来编译)
//make -j4 modules #编译模块,2.6内核并不需要再单独编译了,make已经做过了
make modules_install 安装模块(操作结束后多出目录/lib/modules/2.6.32.63),,
make install #安装2.6内核的系统中,会自动安装内核并更新grub
进入grub启动项,没有倒计时的话开机一直按shift键或者是esc键,启动2.6内核。
这里我编译的内核启动后貌似卡死在紫色屏幕,所以我暂时先放弃了启动2.6内核,尝试ubuntu12.4自带的3.5内核吧。(ps,后续重新编译了一次,能进入2.6内核了)
3.5.0-23-generic
①、hellomod.c #include<linux/init.h> //初始换函数 #include<linux/kernel.h> //内核头文件 #include<linux/module.h> //模块的头文件 MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello,world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye,Cruel world \n"); } module_init(hello_init); module_exit(hello_exit);
</pre><pre name="code" class="cpp"><pre name="code" class="html">②、Makefile obj-m := hello.o KVERSION = $(shell uname -r) #这里编译<span style="white-space: pre;">内核版本可以ls /lib/modules看一下</span> all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
$ modinfo hello.ko
filename: hello.ko$ uname -r
3.5.0-23-generic
④、插入内核并查看insmod hello.ko
#发现没有hello world
#原因书上介绍了由于是虚拟终端,信息不会显示出来,而是存到系统日志中查看日志:
tail -f /var/log/kern.log
Jul 22 17:08:25 u-VirtualBox kernel: [ 5634.200312] Hello,world!
#切换到黑窗口很清楚的看到这个现象
或者cat /var/log/messages #发现没有这个文件,文档说不同的 linux可能路径不同,ubuntu解决办法是在最下面。
直接用下面这个命令看已经加载的模块
$ lsmod
ModuleSize Used by hello 12497 0 [permanent] #这个永久的意思包含的信息量太大了
vesafb 13846 1
⑤移除模块sudo rmmod hellomod
ERROR: Module hellomod does not exist in /proc/modules
#错误应该是来自于[permanent] 这里 应该是无法被卸载!#经测试重启后会消失掉!
原因:系统默认的内核使用gcc版本与当前编译模块的gcc不同导致。
忽然想起来了编译安卓的时候把默认的GCC改成4.4了。。然后我们还是继续看一下。
$ cd /lib/modules/`uname -r`/build/include/generated/
$ cat compile.h
/* This file is auto generated, version 35~precise1-Ubuntu */
/*SMP */#define UTS_MACHINE "x86_64"#define UTS_VERSION "#35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013"
#define LINUX_COMPILE_BY "buildd"
#define LINUX_COMPILE_HOST "komainu"
#define LINUX_COMPILER "gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) "
可以看到官方编译的gcc版本为 4.6.3$gcc -vgcc version 4.4.7 (Ubuntu/Linaro 4.4.7-1ubuntu2) //发现了吧,然后解决办法。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
解决办法(测试成功)
ls -al /usr/bin/gcc*
lrwxrwxrwx 1 root root 7 7月 16 10:57
/usr/bin/gcc -> gcc-4.4-rwxr-xr-x 1 root root 259232 4月 16 2012
/usr/bin/gcc-4.4-rwxr-xr-x 1 root root 353216 4月 16 2012
/usr/bin/gcc-4.6lrwxrwxrwx 1 root root 7 7月 15 16:10
/usr/bin/gcc.bak -> gcc-4.6
那么很简单了把gcc这个软连接指向gcc-4.6就ok了,
之前我有备份直接改一下名字就可以了
创建软连接的方法:ln -s /usr/bin/gcc-4.6 /usr/bin/gcc
重新编译lsmod一下:
Module Size Used byhello 12497 0
rmmod hello
没有出现提示错误查看一下日志吧,
tail-f /var/log/kernel.0
Jul 22 18:04:47 u-VirtualBox kernel: [ 69.715499] Hello,worldJul 22 18:06:00 u-VirtualBox kernel: [ 142.161470] Goodbye
————————————————————————————————————————————————————————————
版本2:
//关于加载模块时指定模块参数的值
#include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> MODULE_LICENSE("Dual BSD/GPL"); static char *whom = "world"; static int howmany = 1; //module_param宏在moduleparam.h定义,charp字符指针, //最后一个参数是权限掩码作为辅助的sysfs入口 //insmod hello howmany=10 whom="hello" 这样改变模块参数 module_param(howmany, int, S_IRUGO); module_param(whom, charp, S_IRUGO); //bool invbool charp int long short uint ulong ushort //数组 module_param_array(name,type,num,perm) //1.数组名 2.数组元素类型 3.长度 4.权限值 static int hello_init(void) { int i; for (i = 0; i < howmany; i++) printk(KERN_ALERT "(%d) Hello, %s\n", i, whom); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit);
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ps::
ubuntu12.04没有/var/log/messages解决
因为出错了找不到这个文件,很奇怪,因为网上介绍说查看这个文件的
然后百度,发现有些版本是没有,不过ubuntu的可以有
编辑/etc/rsyslog.d/50-default.conf
其中有这么一段
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none -/var/log/messages
这是本来就有,却被注释了。现在解注释就行
保存后重启服务:sudo restart rsyslog