内核编译与系统调用
Linux内核编译
一、 前期准备
1.下载内核源码:
先确定自己双系统或者虚拟机中linux的内核版本是多少,用uname –r命令可以查看。
确定内核版本后可以去内核官网www.kernel.org看发布的稳定内核版本,一般不选最新版本,可能存在不兼容问题,所以我下载了接近的版本3.14.40版本。(linux-3.14.40.tar.xz)。
将压缩包复制到/usr/src/文件下,使用sudo cp 下载路径\linux-3.14.40.tar.xz /usr/src命令。
将其解压缩,使用sudo tar –xvf 3.14.40.tar.xz命令解压缩到当前文件夹下。
(基本上关于编写系统函数或编译内核都需要root权限,可以切换到root用户,也可以用sudo命令,我实验时候用sudo)
2.确认自己系统的位数:
可以使用命令查看当前位数(getconf LONG_BIT);
或者如果是图形界面直接点击右上角,有“关于这台计算机的”的选项,显示操作系统的信息。
3.确认自己虚拟机硬盘空间足够大:
一般推荐40G吧,可以使用df –h命令查看当前系统还剩多少可用空间,最好保留20G大小的空间,实际上我编译完内核后估计就用了10G左右。
如果空间不够,在关闭虚拟机上面,在设置里面点击进入硬盘操作界面,使用实用工具里的扩展。
4.线程数(可选):
为了追求编译内核速度,可以将虚拟机中的线程开到4个,同样在设置里面看自己虚拟机线程个数,如果为1,可以改为2或4,我的做法是直接改到4了。
二、编写系统调用函数
1.编写函数:
进入刚才解压缩后的文件,修改文件sudo gedit/usr/src/linux-3.14.40/kernel/sys.c,拉倒文件最后编写自己设定的函数。
在endif之后添加函数,因为添加asmlinkage类型,后面是自己的函数,一定要确保自己编写函数的正确,不然在后面编译会很悲剧,到时候出错就得重新编译一遍,太耗时了。
2.编写系统函数头文件:
修改文件sudo gedit /usr/src/linux-3.14.40/include/linux/syscalls.h。在文件最后的#endif之前添加函数声明
3.为函数添加系统调用号:
修改文件sudo gedit /usr/src/linux-3.14.40/arch/x86/syscall/syscall_32.tbl。(根据刚才查看系统的位数而定,如果是64位就修改syscall_64.tbl文件)。在文件最后添加调用号,可以接着上面的序号继续+1,后面的格式参照上面编写模式。
三、编译内核
1、sudomake mrproper清除内核的目标文件、附属文件以及配置文件(一般第一次编译时候需要使用,主要防止下载的源码包有一些配置文件,影响结果)
2.sudo make clean 清除内核中的目标文件,并不会删除设置文件(在后续需要重新编译时候,只需要make clean就可以了)
3.sudo make oldconfig设置配置文件:这是一种通过已存在.config文件内容,使用该文件内的默认值,只将新版本内核功能新功能提供出来让用户选择,可以简化内核功能挑选过程。(如果使用默认值一直按回车键快速略过也是可以的,ps:选项挺多的)
挑选完后会有上述图片里文字说明配置已写入文件中
4.sudo make bzImage (sudo make bzImage –j4代表用四线程去运行,速度相对较快吧)编译内核:时间大概半个小时左右吧。
编译完成后会有说明内核已经准备完毕
5.sudo make modules (sudo make modules –j4) 编译模块:
这个花费的时间是最长的,我大概花了两个小时左右吧,可能开的是四线程速度提升了一点,这时候cpu占用也会达到90%以上,最好不要继续用你的电脑干其他活占用cpu资源了。
补充:最后如果编译错误,可能原因有:自己的空间不足导致编译中断,这时候你需要去扩容;或者像我一样自己作死编的函数出错了,它也会告诉你出错了。所以千万要保证自己写的函数正确,不然 又得重编,其实在编译内核时候如果你编译错误它也会显示,但是编译会继续,那部分信息会被刷过,不易发现。
6.sudo make modules_install
(sudo make modules_install –j4) 安装模块:
7.sudo make install(sudo make install –j4):
等待安装完毕后,内核部分的编译就已经全部完成啦!!!
四、grub引导
1.修改grub参数:一般来说虚拟机中grub引导菜单会被隐藏,即使更新内核后你也无法选择进入哪个内核,此时可以修改grub参数。
修改文件sudo gedit/etc/default/grub,我的做法是把GRUB_HIDDEN_TIMEOUT注释,直接显示菜单
-
影响grub关键三个因素:
-
GRUB_HIDDEN_TIMEOUT:执行该行的意思为默认启动过程不显示grub,但会有空白界面的延迟,延迟时间就是它的值,空白界面相当于提示我们你可以手动选择进入grub菜单,按shift键强制进入grub菜单界面。
-
将GRUB_HIDDEN_TIMEOUT用#注释掉,它表示菜单直接显示。
-
GRUB_HIDDEN_TIMEOUT_QUIET:true表示不显示空白界面延迟时间,false表示显示。
-
GRUB_TIMEOUT:当GRUB_HIDDEN_TIMEOUT被注释后,表示如果grub界面后停滞的时间。
-
2.grub更新:完成上述操作后就需要更新grub,使用命令sudo update-grub完成grub更新,更新完毕如下:
3.重启虚拟机,进入grub界面,选择高级选项就可以看到各种编译好的内核版本。
进入自己编译的版本后,用uname –r就能发现自己内核版本已经被更换啦。
五、调用系统函数
1.编写调用函数:
记住自己的写的系统调用号,以及函数参数。用gcc编译后运行。
2.输出结果
整个内核编译以及系统调用的过程以及实践完毕。。。过程主要耗时,大家耐心实践吧,在文章最后再加上内核源码内各文件的作用,和grub引导界面下命令的使用。