Vmware根据linux4.19.11打造最小操作系统并启用系统调用(编译环境:kali-4.18)

这段时间,学校要做操作系统课程设计,任务如下:

1、编写一个新系统调用的响应函数,函数的名称和功能由实验者自行定义。把新的系统调用函数嵌入到Linux内核中

2、编写应用程序以测试新的系统调用并输出测试结果

要实现以上设计任务,就必须要独立编译内核进行测试,然而要编译内核需要一些配置,让我们来看看有哪些配置:

第一步,下载linux内核源码并解压:

wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.11.tar.xz
xz -d linux-4.19.11.tar.xz
tar -xvf  linux-4.19.11.tar
cd linux-4.19.11

第二步,安装依赖并运行图形化配置菜单

sudo apt install libncurses5-dev libssl-dev 
sudo apt install build-essential openssl 
sudo apt install zlibc minizip 
sudo apt install libidn11-dev libidn11
sudo apt install bison flex
make menuconfig

中途需要编译一段时间,如果出现问题,可能是因为缺少相关依赖,使用apt安装即可。

第三步,让我们看看图形化配置

注意,第一次进入的界面的配置是根据当前kali系统的配置文件.config自动生成的。这个配置介于命令make allyesconfig和make allnoconfig之间,如果按照这个配置编译,系统内核大约有300M~400M之间,且编译的时间大概需要6个小时,不利于我们的编译和调试,如果按照make allnoconfig配置,1~2分钟之间可以编译好,系统内核也只有500k,但很多功能用不了,显然是不切实际的,所以我们要根据自己的需求,不断去除和添加自己想要的功能。最简便的方法是根据当前配置不断地删减功能,直到不能再减小为止(这样的目的是保留系统的verbose报错功能,输出启动日志以便后续调试,如果一开始就make allnoconfig 虽然系统最小,但很多配置不全,不如使用原系统默认配置,然后一项项删减。)。比如启动日志遇到/bin/sh exists but can't execute,意味着可执行文件执行遇到问题,就需要把excutable file format里面的kernel support for elf binaries启用以及64bit kernel启动,遇到permission denied 就说明可能把自制内核按照在发行版内核同一个分区里导致冲突,因此需要把自制内核安装在另一个分区里。如果遇到can't udev的问题,说明守护程序udev没有打开或者硬盘驱动没有安装,就需要我们安装相应的硬盘驱动,步骤如下:

键入modinfo mptbase,提示如下信息:

root@kali:/home/kali/linux-4.19.11# modinfo mptbase
filename:       /lib/modules/4.18.0-kali2-amd64/kernel/drivers/message/fusion/mptbase.ko
version:        3.04.20
license:        GPL
description:    Fusion MPT base driver
author:         LSI Corporation
srcversion:     AE14687F5D92F8703B5805F
depends:        
retpoline:      Y
intree:         Y
name:           mptbase
vermagic:       4.18.0-kali2-amd64 SMP mod_unload modversions 
parm:           mpt_msi_enable_spi: Enable MSI Support for SPI controllers (default=0) (int)
parm:           mpt_msi_enable_fc: Enable MSI Support for FC controllers (default=0) (int)
parm:           mpt_msi_enable_sas: Enable MSI Support for SAS controllers (default=0) (int)
parm:           mpt_channel_mapping: Mapping id's to channels (default=0) (int)
parm:           mpt_debug_level: debug level - refer to mptdebug.h - (default=0)
parm:           mpt_fwfault_debug:Enable detection of Firmware fault and halt Firmware on fault - (default=0) (int)


可见硬盘驱动为 Fusion MPT base driver

配置PCI总线驱动,依次选"Bus Option"-"Pci support":


前面看到我的磁盘是Scsi类型,因此需要配置Scsi,依次选"Device Drivers"-"Scsi device support"--"Scsi device support","Scsi disk support"


Scsi磁盘需要Sata控制器,这一步比较关键,要从不同厂商的控制器驱动中挑选出合适的驱动。根据前面udevadm的输出我的虚拟机,使用的是Fusion LSI磁盘驱动:依次选取
1)"Device Driver"-"Serial ATA and Parallel ATA driver"-"AHCI SATA support";
2)"Device Driver"-"Fusion MPT device support"-"Fusion MPT ScsiHost driver for SPI";

3)"Device Driver"-"Scsi device support"-"SCSI low-level drivers"-"LSI MPT Fusion SAS 2.0 Device Driver"


设备驱动配置完毕,需要再配置内核支持的文件系统和ELF文件格式。为了方便起见,我们不设置内核支持initramfs,直接用busybox启动。

选取"File Systems"-"The Extend 4(ext4) filesystem"


选取"Executable file formats"-"kernel support for ELF binaries"

"Kernel support for scripts starting with #!"

其他设置:

[*]64 bit kernel

Processor type and features --->

Processor family () --->

[*] Generuc x86 support

Bus options (PCI etc.) --->

[*] PCI support

PCI access mode (Any) --->

Executable file formats / Emulations --->

[*] Kernel support for ELF binaries

[*] Write ELF core dumps with partial segments

[*] Enable the block layer #这步很重要,不然无法启用SCSI

Device Drivers  --->

[*] Block devices --->

<*> Loopback device support

SCSI device support --->

<*> SCSI device support

[*] legacy /proc/scsi/ support (NEW)

<*> SCSI disk support

input device support--->

[*]Generic input interface

[*]event interface

[*]event debugging

*****Input Device Drivers****

[*]keyboards----->

[*]AT keyboard

[*]……keyboard   #键盘驱动可以都选上

Hardware I/O Ports--->   

[*]Serial I/O support

……             #这里可以全选

[*]character devices --->

[*]enable tty

[*] Fusion MPT device support --->

<*> Fusion MPT ScsiHost drivers for SPI

<*> Fusion MPT ScsiHost drivers for FC

<*> Fusion MPT ScsiHost drivers for SAS

<*> Fusion MPT misc device (ioctl) driver

File systems  --->

[*]   The extended 4(ext4) filesystem

[*]   Use ext4 for ext2 filesystem

[*]     Ext4 POSIX Access Control Lists 

[*]     Ext4 Security Labels

[*]     Ext4 Encryption 

设置完成后,选择save,命名为‘.config’, 然后选择exit退出。

第四步、在原系统编译内核

时间不长,大概五六分钟(前提是你精简过),系统编译完大概有2M大小

make clean
make bzImage -j4

第六步、添加硬盘并分区

在vmware里面添加一块大概500MB的SCSI硬盘,重启后执行

fdisk -l

可以看到/dev/sdb装置

进一步分区

fdisk /dev/sdb

输入n后分区形成/dev/sdb1

格式化

mkfs -t ext4 /dev/sdb1

挂载分区

mount /dev/sdb1 /mnt

编译busybox

wget https://busybox.net/downloads/busybox-1.29.3.tar.bz2
tar xvf busybox-1.29.3.tar.bz2
cd busybox-1.29.3
make menuconfig

下面是需要编译进busybox的功能选项。

  General Configuration应该选的选项

   Don't use /usr

      这个选项一定要选,否则make install 后busybox将安装在原系统的/usr下,这将覆盖掉系统原有的命令。

  Build Options

   Build BusyBox as a static binary (no shared libs)

  这个选项也是一定要选择的,这样才能把busybox编译成静态链接的可执行文件,运行时才独立于其他函数库.否则必需要其他库文件才能运行,在单一个linux内核不能使它正常工作。

其它选项都是一些linux基本命令选项,自己需要哪些命令就编译进去,一般用默认的就可以了,配置好后退出并保存。

编译并安装busybox

make
make install 

make install后会在busybox目录下生成一个叫_install的目录,里面有busybox和指向它的链接。

cp _install/* /mnt/           # 将_install下的文件全复制到sdb1  
rm -f /mnt/linuxrc  
cp -r ./examples/bootfloppy/etc /mnt       #将etc下的配置文件拷到sdb1下  
cd /mnt/  
mkdir proc mnt usr var tmp dev sys         #创建目录  
cp -a /dev/{console,tty,tty2} dev/    #将原系统的设备文件复制到自制系统
mkdir dev/input
cp -r /dev/input/* dev/input/
cp /root/linux-4.19.11/arch/x86/boot/bzImage /mnt/bzImage #复制内核

第七步、更新grub

打开grub配置文件

vi /etc/grub.d/40_custom #不同的系统前面的序号可能不一样

在末尾添加如下信息

menuentry "My Linux-4.19.11" {

insmod ext2 #ext2包括了ext3、ext4

set root='(hd1,1)'

linux /bzImage ro root=/dev/sdb1

}

更新grub

update-grub

重启系统,在grub菜单选择My Linux-4.19.11如果看到类似以下界面说明编译成功

第八步、添加系统调用

回到原系统,更改linux源码以下文件:

vi /root/linux-4.19.11/arch/x86/entry/syscalls/syscall_64.tbl

添加如下两个系统调用,注意这两种系统调用的形式不太一样,主要是为了传参,后面会讲到。

修改头文件,添加如下两个函数原型

vi /root/linux-4.19.11/include/linux/syscall.h

修改sys.c源文件,添加如下函数定义

vi /root/linux-4.19.11/kernel/sys.c
long sys_hello(void)
{
printk("hello world");
return 1;
}
SYSCALL_DEFINE2(add,int,a,int,b)
{
printk("a:%d \n",a);
printk("b:%d \n",b);
printk("a+b:%d \n",a+b);
return a+b;
}

注意以上函数定义是不一样的,前者是直接定义,后者是通过宏来定义,之后sys_add会被编译器自动替换为__x64_sys_add目的是为了让系统调用实现传参,相当于一个接口。SYSCALL_DEFINE2意思是有两个参数,int a,int b。

之后重新编译内核并复制到新硬盘。

第九步、编写测试程序

目的是为了手动实现系统调用,使用gcc编译好并输出为test1 文件

#include<stdio.h>
#include<linux/kernel.h>
#include<sys/syscall.h>
#include<unistd.h>
#include<stdlib.h>

int main(int argc,char *argv[])
{
	long int amma;
	if(argc==4)amma=syscall(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]));
	else amma=syscall(atoi(argv[1]));
	printf("System call %d return %ld\n",atoi(argv[1]),amma);
	return 0;
}

复制test1到新硬盘

cp test1 /mnt/bin/test1

目前在新系统里执行test1是不行的,所以需要分析test1的文件类型

string test1

由输出信息可见,执行该文件需要The GNU C Library的部分库,所以要从原系统复制过去

mkdir /mnt/lib/x86_64-linux-gnu
mkdir /mnt/lib64
cp -a /lib/x86_64-linux-gnu/{libc.so.6,ld-2.28.so,libc-2.28.so} /mnt/lib/x86_64-linux-gnu/ 
cp /lib64/ld-linux-x86-64.so.2 /lib64/

注意除了两个.so结尾的文件,其余复制过去的都是软连接,软连接指向那两个文件,如果软连接发生故障可以用ln -s 修复。

重启进入自制系统,如果测试成功,会有如下结果:

至此,系统调用完成。

---------------------------------------------------------------------------

配置文件:

https://github.com/fjh1997/vmware-linux-minimize-kernel-student/blob/master/.config

参考:

VMware中打造最小Linux系统(一)——构建内核&文件系统 - yejingx的专栏 - CSDN博客

https://blog.csdn.net/yejingx/article/details/6525405

制作最小linux内核(1) - lixiangminghate的专栏 - CSDN博客

https://blog.csdn.net/lixiangminghate/article/details/55224412

linux添加系统调用总结(内核版本4.4.4) - sinat_28750977的博客 - CSDN博客

https://blog.csdn.net/sinat_28750977/article/details/50837996

Linux系统调用之SYSCALL_DEFINE - 柠檬C的专栏 - CSDN博客

https://blog.csdn.net/hxmhyp/article/details/22699669

ubuntu18.04 编译内核 学习记录 - Hynn01的博客 - CSDN博客

https://blog.csdn.net/weixin_38180645/article/details/82856407

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值