一个计算机技术爱好者与学习者

0%

Ubuntu Kylin编译内核和添加系统调用

1. 下载内核

1.1. 查看当前内核版本

uname -a

可以看到,当前内核版本为3.16.0。

1.2. 获取当前版本内核源码

sudo apt-get install linux-source
内核源码默认下载到/usr/src文件夹下,这里,我们就使用这套源码。

1.3. 官方下载地址

https://www.kernel.org/
这个网站,你可以找到最新的内核版本,如果要想要给内核升级,可以来这里下载。

2. 解压内核

cd /usr/src/
tar -jvf linux-source-3.16.0.tar.bz2
解压失败:

1
2
tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options
Try 'tar --help' or 'tar --usage' for more information.

添加一个参数x:
tar -xjvf linux-source-3.16.0.tar.bz2
再次失败,各种Permission denied。

su
tar -xjvf linux-source-3.16.0.tar.bz2
虽然速度很慢(3分钟左右),但是好歹解压成功了。

3. 添加系统调用

3.1. 修改sys.c

cd linux-source-3.16.0/kernel/
gedit sys.c
添加如下代码:

1
2
3
4
5
6
7
8
/*
*new systemcall added by voidking
*/
asmlinkage int sys_callvoidking(void)
{
printk("You are handsome,VoidKing!");
return 0;
}

3.2. 修改syscall_32.tbl

cd /usr/src/linux-source-3.16.0/arch/x86/syscalls
gedit syscall_32.tbl
在最后一行插入

1
355	i386	callvoidking		sys_callvoidking

3.3. 修改syscalls.h

cd /usr/src/linux-source-3.16.0/include/linux/
gedit syscalls.h
#endif前添加:

1
asmlinkage int sys_callvoidking(void);

4. 编译准备

4.1. libncurses5-dev

安装nucurses库,为了make menuconfig调用。
apt-get install libncurses5-dev

4.2. 配置文件

把原先系统的配置文件拷贝到当前源码目录。
cp /boot/config-\uname -r` .config`

4.3. 加载配置文件

make menuconfig,打开编译配置界面,load,ok,save,exit。


5. 编译命令

5.1. 编译内核

make -j8或者make bzImage,前者更快一点。

有些同学要两个小时才能编译完成,郝同学使用VirtualBox,只用了20分钟,电脑配置之牛逼可见一斑!哇哈哈哈!

5.2. 编译模块

make modules,编译模块时,郝同学自己添加的系统调用出现了警告,不过不影响接下来的编译。
一个小时之后。。。噗!要吐血了,之前分给虚拟机8G存储空间,没想到编译过程中,空间不足了,没法继续编译。。。

5.3. 扩展Ubuntu空间

1、首先关闭虚拟机,在设置中给Ubuntu再添加一块虚拟硬盘。
2、打开虚拟机,cd /dev
3、fdisk sdb
4、命令p:查看当前新盘状态。
5、命令n:创建一个新的分区。
6、两个选项e(扩展分区)和p(主分区),选择p。
7、连续两次回车,使用默认的起始和结束sector。
8、创建了一个sdb1,大小为整块虚拟硬盘。
9、命令w:保存退出。
10、mkfs -t ext4 sdb1,格式化。
11、cd /mntmkdir sdb1mount /dev/sdb1 sdb1
12、cd sdb1cp -rv /usr/src/linux-source-3.16.0 .
13、umount sdb1mount /dev/sdb1 /usr/src

5.4. 重新编译模块

cd /usr/src/linux-source-3.16.0make modules
等。。。再等。。。继续等。。。四个小时之后,提示空间不足。。。我靠,你丫到底需要多大空间?8G的空间不够你编译程序用的!!!哭了。。。

5.5. 加速编译

寻找加速编译内核的办法,发现,似乎make -j8等于make bzImagemake modules
去掉编译模块这个步骤试试:
make mrpropermake cleanmake -j8,然后make modules_install。报错:

1
2
3
4
5
6
7
  INSTALL arch/x86/crypto/aes-x86_64.ko
cp: cannot statarch/x86/crypto/aes-x86_64.ko’: No such file or directory
Can't read private key
scripts/Makefile.modinst:30: recipe for target 'arch/x86/crypto/aes-x86_64.ko' failed
make[1]: *** [arch/x86/crypto/aes-x86_64.ko] Error 2
Makefile:1089: recipe for target '_modinst_' failed
make: *** [_modinst_] Error 2


猜测是配置文件.config文件有问题,换成/usr/src/linux-headers-3.16.0-23-generic目录下的.config文件。重新编译,安装,还是报同样错误。那就再加上编译模块这个步骤吧!

5.6. 第三次编译模块

make -j8 modules,大概四个小时之后,终于编译完成。

安装模块报错,和make -j8编译后直接安装模块报错相同。给跪了,能不能愉快地玩耍了!

5.7. 找到错误

后来,仔细检查了前面的步骤。发现修改syscalls.h的时候,声明类型写错了,本该是int,却写成了long类型。修改成int,一路顺利。实践证明,make -j8等于make bzImagemake modules

5.8. 安装模块

make modules_install

5.9. 建立映像文件

建立要载入ramdisk的映像文件
mkinitramfs -o /boot/initrd-mylinux.img
cd /bootll

5.10. 安装内核

make install

6. 更新grub引导

update-grub

7. 测试

7.1. 选择新内核

开机时,选择新内核引导系统。

7.2. voidking.c

新建文件voidking.c,内容如下:

1
2
3
4
5
6
7
8
9
10
#include <unistd.h>
#include <stdio.h>

#define callvoidking 355

int main()
{
syscall(callvoidking);
return 0;
}

7.3. 编译执行

gcc -o voidking voidking.c
./voidking
最终什么都没有显示出来,不知道错在哪里。。。也许是sys.c中的函数没有写好,不重做了,整个流程耗时太久,领会精神就够了。

8. 小结

为Linux添加新的系统调用,主要包括有4个步骤:编写系统调用服务例程;添加系统调用号;修改系统调用表;重新编译内核并测试新添加的系统调用。

虽然这次实验最终失败了,但是,我掌握了添加系统调用和编译内核的流程,培养了耐心以及分析解决问题的能力。也算是收获颇丰,吼吼!

9. 参考文档

Ubuntu 14.04 TLS 内核升级和添加系统调用
http://yunpan.cn/cQtsTfkbeTPvG 访问密码 adce


如何实现一个新的系统调用
http://book.51cto.com/art/201007/213651.htm


ubuntu下重新编译内核
http://m.blog.csdn.net/blog/chen_jianjian/42168449


Ubuntu Linux内核编译步骤
http://www.linuxidc.com/Linux/2012-03/57303.htm


Add a system call to the linux kernel in Ubuntu
http://www.franksthinktank.com/howto/addsyscall/


Ubuntu添加系统调用
http://gnodsy.blog.163.com/blog/static/17754713320112135352447/


Ubuntu内核的重新编译安装
http://www.linuxidc.com/Linux/2009-12/23721.htm