Linux内核编译

前言

我第一次接触Linux,还是几年前学怎么是去破解别人家的wifi然后做ARP欺骗的那会,用的是Kali Linux。后来没怎么继续钻研也就忘得差不多了。本学期所修的操作系统课要求做编译和替换Linux内核的作业,而自己在实验过程中遇到过很多问题,参考了多篇博客,也踩了很多别人博客里的坑,所以也就写下这篇博客归纳下。

1 准备

1.1 实验环境

Vmware12 + ubuntu10.10(32bits) + linux-2.6.32.71.tar.xz
未采用最新版的原因: 个人觉得对于仅仅是学习Linux内核编译这个过程而言,不需要追求最新的环境,做到理解这个过程就足够了,况且老版本资料相对多一些。

1.2 其他参考链接与下载

在编译过程中,我主要参考了一篇博客,这里也贴出来,方便大家对照学习。**同时ubuntu和内核文件的下载也在下面这篇博客里边,自取。Linux 内核编译(三天吐血经历!)

2 安装Linux

2.1 系统资源分配

在Vmware中安装Linux时要注意设置以下配置参数
1)处理器: 尽量多分配。编译内核的时候能够速度快一些,减少等待时间(如果电脑配置低,真的会等上一两个小时)。
2)内存:2G 足够,操作不卡顿。
3)磁盘:40G 及以上(自己第一次做的时候,按默认分配20G,后来磁盘空间不足,没办法继续后面的操作。而且Linux安装完成后再分配空间会比较麻烦。可以参考这篇文章扩容

2.2 安装完成

Vmware安装系统很简单,不多解释。值得注意的是,安装完成后,最好保持系统语言为英语,这使得我们之后输入命令变得方便很多。

2.3 复制内核,并解压

1)将内核文件拷贝至/usr/src目录下:
得益于Vmware Tools的支持,我们可以直接将内核文件通过拖拽的方式复制到Linux系统中。
2)打开终端,获得管理员权限:

sudo su

3)解压缩:

cd /usr/src							//进入目录
xz -d linux-2.6.32.71.tar.xz		//解压成.tar文件
tar xvf linux-2.6.32.71.tar			//解压

3 替换内核

3.1 打开sys.c文件

sys.c这个文件中包含了绝大部分的系统调用函数的实现。

gedit /usr/src/linux-2.6.32.71/kernel/sys.c

gedit是一款文本编辑器,带有语法高亮。

3.2 在sys.c文件的末尾增加系统调用

我们要增加的是下面这个函数方法,在调用后打印一行文字。

asmlinkage int sys_mycall(int number)
{                                    
	printk("Hello my linux world!"); 
	return number;
}

完成更改后,保存并退出。

3.3 注册系统调用

Gedit /usr/src/linux-2.6.32.71/arch/x86/kernel/syscall_table_ 32.S

在文件末尾添加变量:

.long sys_mycall

完成更改后,保存并退出。

3.4 设置系统号

gedit /usr/src/linux-2.6.32.71/arch/x86/include/asm/unistd_32.h

1)在#define __NR_xxxxx之后添加:

#define __NR_mycall   337

2)将#define _NR_syscalls 337改为338
要保证_NR_syscalls相当于系统调用边界,所有系统号都要小于它。

4 编译内核

逐条键入以下命令,确保所有命令正确运行无错误。

cd /usr/src/linux-2.6.32.71		 	//进入目录
make mrproper								  
make clean									  
make oldconfig							  
make bzImage						//编译内核
make modules						//编译模块
make modules_install				//安装模块
make install						//生成config

这个过程中耗时最久的是make bzImage与make modules。大概耗时会超过一个小时,所以可以休息下。如果我们自定义的系统调用存在错误,会在这个编译过程中报告错误并中断。
(在前面贴的那篇博客中,并没有make install这步,导致后面更新grub引导表没有新内核的.config文件,无法继续进行下一步,后来通过查看了其他几篇博客才找到这个问题。这也提醒了我,自己在写完博客后一定要反复检查自己的博客,及时修正内容,少让读者走弯路。)

5 拷贝内核

5.1 查看编译完成结果

进入/lib/modules中,左边没有generic的文件夹是新的内核模块

5.2 拷贝内核到/boot中

cp /usr/src/linux-2.6.32.71/arch/i386/boot/bzImage /boot/vmlinuz-2.6.32.71-mykernel

5.3 创建initrd文件

initrd文件中包含了系统的各种可执行文件和驱动程序。

mkinitramfs -o /boot/initrd.img-2.6.32.71

5.4 更新grub引导表

修改grub引导表,以引导启动新的内核版本。
这个是非常重要的一步,如果没有正确的完成,可能会导致系统重启后,无法再进入系统!然后就正很苦逼的将以上操作全部重来!所以要非常非常仔细。

gedit /boot/grub/grub.cfg			//打开引导表文件

1)找到我们所需要修改的部分:
需要修改的部分包含在一下的结构中,其中共有1、2两段代码

### BEGIN/etc/grub.d/10_linux ### 
    1……
    2……  
### END/etc/grub.d/10_linux ###

2)复制begin与end之间的1、2代码段,并粘贴到begin之后

### BEGIN/etc/grub.d/10_linux ### 
    N1……
    N2……
    1……
    2……  
### END/etc/grub.d/10_linux ###

3)修改N1与N2中的版本号为新内核的版本号(红色字体部分

menuentry ‘Ubuntu, with Linux 2.6.32.71 ’ --class ubuntu --class gnu-linux --class gnu --class os
{
    recordfail
    insmod part_msdos
    insmod ext2
    set root=’(hd0,msdos1)’
    search --no-floppy --fs-uuid --set dd02b80e-a0f5-4a38-b6a5-bbab00e394bb
    linux /boot/vmlinuz-2.6.32.71-mykernel root=UUID=dd02b80e-a0f5-4a38-b6a5-bbab00e394bb ro quiet splash
    initrd /boot/initrd.img-2.6.32.71
}

menuentry ‘Ubuntu, with Linux 2.6.32.71 (recovery mode)’ --class ubuntu --class gnu-linux --class gnu --class os
{
    recordfail
    insmod part_msdos
    insmod ext2
    set root=’(hd0,msdos1)’
    search --no-floppy --fs-uuid --set dd02b80e-a0f5-4a38-b6a5-bbab00e394bb
    echo ‘Loading Linux 2.6.32.71 …’
    linux /boot/vmlinuz-2.6.32.71-mykernel root=UUID=dd02b80e-a0f5-4a38-b6a5-bbab00e394bb ro single
echo ‘Loading initial ramdisk …’
    initrd /boot/initrd.img-2.6.32.71
}
修改完成后,保存并退出。

6 最后一步

6.1 备份initrid文件

cd /boot 
cp initrd.img-2.6.32.71 initrd-2.6.32.71.old

6.2 修改initrid文件

命令较多,注意命令里的空格

depmod -a
update-initramfs -k 2.6.32.71 -c
cd /tmp
gzip -dc /boot/initrd.img-2.6.32.71| cpio -id
touch lib/modules/2.6.32.71/modules.dep
find ./ | cpio -H newc -o > /boot/initrd.img-2.6.32.71.new
gzip /boot/initrd.img-2.6.32.71.new
cd /boot
mv initrd.img-2.6.32.71.new.gz initrd.img-2.6.32.71

执行完以上命令,替换和编译都已经全部完成了,下面可以重启系统,查看结果了。

reboot					//重启

7 查看结果

7.1 查看内核版本

sudo su					//获得管理员权限
uname -a
可以看到内核已经从2.6.35.22替换到了2.6.32.71

7.2 测试自定义系统调用

1)在终端中打开gedit工具

gedit

2)键入测试代码

#include<stdio.h>
int main()
{
	syscall(337, 1);
    return 0;
}

保存为mytest.c,位置为Desktop
3)进入桌面,编译程序

cd /Desktop					
gcc -o mytest mytest.c		
./mytest				

4)运行程序

dmesg -c						

5)查看结果

8 结语

以上便完成了Linux内核的编译和替换。个人对linux的理解不深,所以如果以上内容存在错误与不足,非常欢迎评论指出。 另外除了文中提到的一些细节,还有很多坑也遇到过没有细说,环境不同所遇到的问题也不尽相同,欢迎留言评论。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值