今天在做Linux系统调用与内核编译的实验,主要任务有两个:
1)添加一个新的系统调用:mysyscall,功能仅为打印一条语句。
2)编译内核。
实验步骤如下:
1.在官网(www.kernel.org)上下载最新的内核压缩包,本次实验版本为:linux-2.6.36.2.tar.bz2
2.以root登录,将内核包复制到usr/src下:cp linux-2.6.36.tar.bz2 /usr/src
3.解压:tar -xjvf linux-2.6.36.2.tar.bz2
4.修改以下文件夹下的3个文件:
①编辑/usr/src/ linux-2.6.36.2/kernel/sys.c文件,添加系统调用函数:
SYSCALL_DEFINE1(mysyscall,int, number)
{
printk("call number is %d/n",number);
return number;
}
②编辑/usr/src/linux-2.6.36.2/arch/x86/kernel/syscall_table_32.S,在文件最后加上一行:
.long sys_mysyscall /* 341 */
从这个文件来确定mysyscall的系统调用号,mysyscall的系统调用号等于最后一行的系统调用号+1。如最后行对应的系统调用号是340,mysyscall的系统调用号为341。
③修改/usr/src/linux-2.6.36.2/arch/x86/include/asm/unistd_32.h,添加一行将mysyscall与确定的系统调用号对应起来:#define __NR_mysyscall 341
5.重新编译内核
在终端输入命令,进入源代码文件夹:cd /usr/src/linux-2.6.36.2 ,执行如下命令:
make mrproper
①配置内核(两种方法):
1)手动:make menuconfig(出现菜单配置界面)
2)采用内核的配置选项:
make allyesconfig
尽可能地使用''y''设置特征值,来建立一个配置文件,得到一份最详细的代码
make allmodconfig
尽可能地使用''m''设置特征值,来建立一个配置文件
make allnoconfig
尽可能地使用''n''设置特征值,来建立一个配置文件 ,得到一份精简的代码
关于是直接编进内核还是编译成模块的一点参考:若是内核一定需要的功能,不用多说直接编进内核;可能在将来会用到的功能,尽量编译成模块;完全不了解的内核功能就保留默认值。
首页的几个选项介绍:
(1)General setup
与Linux最相关的程序互动、内核版本说明、是否使用开发中程序代码等信息都在这里设置的。基本上,保留默认值即可。不要随便取消下面的任何一个选项,可能造成某些程序无法被同时执行的困境。
(2)Processor type and features
挑选主机的实际CPU形式。
(3)Power management and ACPI options
系统电源管理机制。
(4)Executable file formats/Emulations
编译成可执行文件的格式,是给Linux内核运行可执行文件之用的数据。
(5)Networking support
内核的网络功能,包含了防火墙的相关选项,就是防火墙iptables这个数据。建议编成模块。
(6)Device Drivers
各项设备的驱动程序,这是所有硬件设备的驱动程序库。
(7)Security Options、Cryptographic API
信息安全、密码应用
②编译内核(结果文件会放到源代码所在目录)
make bzImage (耗时很长)
以上命令执行完毕后,会在当前目录下生成一个名为System.map的文件,会在/usr/src/linux-2.6.36.2/arch/x86/boot/下生成一个bzImage文件。
③编译模块(结果文件会放到/lib目录下)
make modules
实际上,只要直接执行make命令就会同时编译内核和模块,模块编译完成后执行“make modules_install”更新模块和驱动程序。
④拷贝内核文件到/boot下,在终端执行以下命令:
cp /usr/src/linux-2.6.36.2/arch/x86/boot/bzImage /boot/vmlinuz-2.6.36.2 (拷贝内核镜像)
cp /usr/src/linux-2.6.36.2/System.map /boot/System.map-2.6.36.2 (拷贝符号表)
⑤建立ramfs和ramdisk
cd /boot (进入/boot目录)
生成ramfs:mkinitrd initramfs-2.6.36.2.img 2.6.36.2
生成ramdisk:mkinitrd initrd-2.6.36.2.img 2.6.36.2
(注:ramfs与ramdisk选一个就行,下面grub.conf文件里initrd对应生成的文件)
注:这一步可能会提示一些错误,不过不影响后面的实验~
⑥编辑启动配置文件grub
编辑/boot/grub/grub.conf。在grub.conf文件中,每一个title标签表示一个启动项,仿照第一段title的写法,编写新内核的启动项,其中kernel和initrd使用新拷贝过来的vmlinz—版本号文件和initrd-2.6.36.2.img文件。
原来的grub.conf文件:
default=0
timeout=0
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Fedora (2.6.33.3-85.fc13.i686)
root (hd0,0)
kernel /vmlinuz-2.6.33.3-85.fc13.i686 ro root=/dev/mapper/vg_fedora13-lv_root rd_LVM_LV=vg_fedora13/lv_root rd_LVM_LV=vg_fedora13/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=zh_CN.UTF-8 KEYTABLE=us rhgb quiet
initrd /initramfs-2.6.33.3-85.fc13.i686.img
修改后的grub.conf文件:
default=1
timeout=15
splashimage=(hd0,0)/grub/splash.xpm.gz
#hiddenmenu
title Fedora (2.6.33.3-85.fc13.i686)
root (hd0,0)
kernel /vmlinuz-2.6.33.3-85.fc13.i686 ro root=/dev/mapper/vg_fedora13-lv_root rd_LVM_LV=vg_fedora13/lv_root rd_LVM_LV=vg_fedora13/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=zh_CN.UTF-8 KEYTABLE=us rhgb quiet
initrd /initramfs-2.6.33.3-85.fc13.i686.img
title Fedora(2.6.36.2)
root(hd0,0)
kernel /vmlinuz-2.6.36.2 ro root=/dev/mapper/vg_fedora13-lv_root rd_LVM_LV=vg_fedora13/lv_root rd_LVM_LV=vg_fedora13/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=zh_CN.UTF-8 KEYTABLE=us rhgb quiet
initrd /initramfs-2.6.36.2.img
⑦重新启动系统,使用新生成的内核。
⑧编写测试程序testcall.c,测试新系统调用。
1)新建文件testcall.c:
//testcall.c
int main()
{
syscall(341,100); /*341是新添加的系统调用号,100是测试参数*/
return 0;
}
2)终端编译 gcc –o testcall testcall.c
3)运行 ./testcall
4)查看结果 :终端运行命令dmesg,会看到在最后一行输出 call number is 100