前言

众口难调,所以干脆,“虚拟机管理软件+虚拟机+内核”,所有步骤都写上去了,友友们可以根据自己的需求翻着看呀~

环境

VMware15,找的资源下的,挺安全的,还可靠
Ubuntu 16.04,32位系统,内存2GB,存储空间40GB,1个处理器,4个内核
新增内核版本:linux-4.16.10
gcc版本:诶~不需要下,就用系统自带的就彳亍
在这里插入图片描述

资源下载链接合集+下载说明

VMware15 + Ubuntu16.04镜像文件(32位系统)下载链接
提取码:xzas

4.16.10内核下载链接
↑这玩意儿先别急着装,虚拟机装好了之后再去虚拟机里面用浏览器下载,免得还要把压缩包从主机移到虚拟机里,省点事儿~

基本流程

1.装VMware 15

前面的步骤都无关紧要,用默认即可,就是这几个图要注意看看!!!
1.取消这两个勾选!!!
取消勾选!!!2.密钥,都可以用~
白嫖密钥

2.配置虚拟机

照着图做就好:
1.选典型,然后下一步
典型2.选择你下载好的镜像文件,然后下一步
在这里插入图片描述

3.设置用户名,密码,密码不许带数字!!!怎么简单怎么来,免得后面麻烦,下一步
在这里插入图片描述4.给虚拟机起个名字,随便起~没影响,然后设置虚拟机放在电脑的哪个位置(40个G呢!!千万别往C盘放!!虽然不影响实验,但鼠鼠有精神洁癖,所以,为了我,不要放C盘!!!不要!!)
在这里插入图片描述5.设置存储空间、选择单个文件!!!
在这里插入图片描述6.一定一定!!要自定义硬件!!把内存、内核数调高一点!!不然后面编译内核要花一年!!(>1个小时)
内存2GB,处理器1个,每个处理器的内核数量4个
觉得电脑配置高的友友们当然可以把内存设置成4GB,核数再搞多一些,但我这个配置就够用了,第一次编译内核只花了20来分钟。
在这里插入图片描述

在这里插入图片描述完成!打开虚拟机。
打得开嘛?我反正是要蓝屏好几次,电脑重启之后,才能打得开的。建议尝试打开虚拟机时,VMware会提示你“啥啥啥没找到,要每次运行此虚拟机时都尝试连接吗?”如下图
在这里插入图片描述

这个时候,就等着别动,等你电脑的风扇转得没那么厉害了再选择“是”,这样蓝屏的概率会小一些

↓开始废话,乐意看就看,不影响实验
我的小破电脑一般是要蓝屏三到四次,再打开就好啦!头一次蓝屏还给我吓得不轻(没见过世面是这样的),这两三天连着崩了20+次,也习惯了~

3.虚拟机内安装操作系统

自己的一点理解:Ubuntu镜像文件就是在这一步起作用的,它会看你现在的虚拟机里有没有操作系统,没有它就给你装上,有就直接把操作系统给你调出来。
这一步就没图可贴了,放着不管,它自己会给你装好的,要是有可选的界面就按自己需求随便选选,一般就是语言啥的,说实话,英文也没那么难看。

好了~虚拟机打开了,现在就是虚拟机内的操作了
在这里插入图片描述

4.虚拟机安装新的内核

诶!安装新的内核,就是文章开始那个链接,这里再贴一次:
https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.16.10.tar.xz

1.链接输入到Ubuntu自带的火狐浏览器里,就会让你下载。
选择Save File,保存文件,点OK
在这里插入图片描述2.下载好的内核压缩文件就在这个文件夹里,去这个文件夹里,右键打开终端
在这里插入图片描述3.然后,咱得想办法把这个内核压缩文件拷贝到Ubuntu里的一个专门存内核的文件夹里,/usr/src,诶!我直接Ctrl+C、Ctrl+V,能行吗?不能行
/usr/src是干嘛的?放内核的啊~怎么可能让你随便亵渎!(写读)
所以咱先得把root权限要到手,然后就可以用命令随便亵渎 了,输入以下命令,root权限轻松带回家!

sudo -s

或者sudo su
这两个命令是一样的。
然后会让你输密码,就是你的虚拟机登录密码,命令行里,你输入的密码不会回显,所以只管输入就行。
在这里插入图片描述然后,拷贝,copy,简写一下就是cp
拷贝谁呢?拷贝linux-4.16.10.tar.xz这个文件
拷到哪去呢?拷到专门放内核的文件夹里,/usr/src
命令就出来了:cp linux-4.16.10.tar.xz /usr/src

4.好!现在就来看看/usr/src里有没有:
在这里插入图片描述有!然后干嘛呢?然后解压呗~在/usr/src这个文件夹里右键打开终端,输入解压命令:sudo tar -xvf linux-4.16.10
(Q:诶!有的地方没说要加sudo啊~你这儿咋有?
A:“sudo +命令”的格式用得很多,这条命令的意思是说,将命令以root权限执行,如果你现在没有root权限,它就会让你输密码,然后把root权限搞到手,如果有root权限,那它就舒服了~啥也不用干)
在这里插入图片描述解压完成!喜提linux-4.16.10内核!
在这里插入图片描述

5.添加系统调用

系统调用,说白了,内核文件夹里给你实现好的一堆“比较特殊”的函数,那咱现在要加系统调用,就是要去内核里写个函数,嗯!听上去感觉不难嘛~

a.先在内核给新函数登个记(register)

低版本的内核(比如linux-2.x的核),登记可麻烦了,到处改文件,什么entry.S、syscall_32_.c…一堆,我可懒了,所以选的相对高版本的内核linux-4.16.10,高版本内核简化了系统调用登记的步骤,诶~用着舒服
找一个文件夹,它的绝对路径为:

/usr/src/linux-4.16.10/arch/x86/entry/syscalls

进去之后看这两个文件,你的虚拟机的操作系统是32位就改syscall_32.tbl,64位就改syscall_64.tbl
不知道系统是多少位的?没关系!有命令,输一下看一下就知道喽~打开终端,输入命令getconf LONG_BIT,看看你现在的操作系统中,long型数据占几位,就知道系统是几位的了

在这里插入图片描述好!我的long型数据是32位的,所以我的系统是32位的,所以我打开syscall_32.tbl
在这里插入图片描述
但是!这个文件双击打开后不能保存,因为,,,没有权限啊~这还是在内核里!没权限啥也干不了,走命令抢权限,很熟悉了,sudo -s
然后,用gedit打开该文件(gedit,linux系统里的记事本),还是得输命令:

gedit syscall_32.tbl

命令的意思是:以gedit的方式打开syscall_32.tbl

好!开始登记!
咱要写的系统调用是要实现文件拷贝,所以给这个函数起了个名字叫filecopy
然后对应的核态函数名字就加个"sys_"前缀就行,sys_filecopy
直接去文件最后一行,先给咱们的系统调用整个系统调用号,只要是没被占用的就行,我这儿懒得想,就直接最后一个加一,385,这个号记住!!之后写测试程序就要用这个号来调咱们写的函数。
系统是32位的,所以要跟内核说一声,我这是32位系统写的函数,加一个i386
在这里插入图片描述64位系统的友友们就在syscall_64.tbl里的这个位置加一行:
在这里插入图片描述64表示是64位系统,别加到下面去了哟~因为我也没试过加在下面会发生什么,出问题我也没招儿

登记完成!!

b.函数声明(declare)

要写函数,标准的做法就是“声明+定义”,咱先把声明做了
这一步不区分32位系统还是64位系统,都一样。
找这个文件:/usr/src/linux-4.16.10/arch/x86/include/asm/syscalls.h
在这里插入图片描述咱就是在这里面声明新的系统调用
还是在内核操作文件,老规矩,右键开终端,先抢权限:sudo -s
然后,用gedit打开syscalls.h文件:gedit syscalls.h
找个地方声明函数:
在这里插入图片描述asmlinkage是个修饰符,照着加上就好,问就是我也不知道这是个啥
源文件路径:const char *srcFile, 目标文件路径:const char *dstFile
声明别乱放嗷~千万别放到#ifdef…#endif里面去了,不然写测试的时候还要#define一堆东西,你乐意?我反正不乐意哈

OK!声明完成!保存退出

c.函数定义(define)

终于!开始实现系统调用的功能了!我们要实现的是文件拷贝功能
首先,得知道咱得去哪写,去找这个文件
绝对路径:/usr/src/linux-4.16.10/kernel/sys.c
要在这里面写函数,老规矩,右键终端,抢权限:sudo -s
gedit打开sys.c文件:gedit sys.c
在这里插入图片描述开始写!首先,先加个头文件进去,linkage.h 我也不知道是干嘛的,加就完了!
在这里插入图片描述实现功能,文件拷贝,很简单啊~很简单
一定要写在文件尾!!那个#endif的下一行!!大一C语言里讲的编译预处理中说到过,#ifdef…#endif是干什么的应该大致知道,不赘述
在这里插入图片描述

Q:为啥不用open/write/read/printf这些函数来写,而是用这些丑不拉几的函数呢?
A:这是在内核里实现函数,都是在核态运行的,学名好像是叫内核开发什么的,一般函数都是不能用的,要用它们对应的内核函数来写,所以要用sys_open这些丑不拉几的函数

用户态函数核态函数
opensys_open
readsys_read
writesys_write
printfprintk

参数基本相同,唯一要说的是printk,能看到我写了个 printk(KERN_EMERG "NULL path error\n"); 这里不是写错了,就是这么用的,这个KERN_EMERG是printk的打印级别里,最高的一级,字面上也好懂,emerg→emergency,告诉内核,这是个紧急事件,给爷输出到控制台!
不写的话,printk的默认打印级别不会输出到控制台的,而是输出到其它文件里了,不好找。

Q:这个mm_segment_t fs; 又是在干嘛?
A:不知道,我猜是段保护,汇编里面学过,但我没学好,什么Code Segment(代码段), Data Segment(数据段), Stack Segment(堆栈段),fs是什么段我还真忘了,这里也不太清楚为什么要做段保护,但是不做出错,没处说理去~

代码贴贴:

#define BUFSIZE 64
asmlinkage void sys_filecopy(const char *srcFile, const char *dstFile){
	char buf[BUFSIZE]="";
	int src_fd;
	int dst_fd;
	int readLen;
	
	mm_segment_t fs;
	fs = get_fs();   // Save segment address
	// set current f-segment pointer with data-segment address
	set_fs(get_ds());
	
	if(srcFile==NULL || dstFile==NULL){
		printk(KERN_EMERG "NULL path error!\n");
		// Recover f-segment address
		set_fs(fs);
		return;
	}
	
	src_fd = sys_open(srcFile, O_RDONLY, 0);
	dst_fd = sys_open(dstFile, O_WRONLY | O_CREAT, 0600);
	if(src_fd < 0){
		printk(KERN_EMERG "srcFile does not exist!\n");
		sys_close(dst_fd);
		// Recover f-segment address
		set_fs(fs);
		return;
	}
	
	while((readLen = sys_read(src_fd, buf, BUFSIZE)) > 0){
		sys_write(dst_fd, buf, readLen);
	}
	
	printk(KERN_EMERG "Copied successfully!\n");
	sys_close(dst_fd);
	sys_close(src_fd);
	// Recover f-segment address
	set_fs(fs);
}

6.编译内核

好啦!功能实现完成!之后就要编译这个内核了~
下载下来的内核里只有一堆.c文件之类的配置文件,可以就把内核想象成一个C语言的project,只有一堆资源文件,还没生成产品,这一步就让它生成产品了,开始编译!

a.准备工作

先打开这个文件夹:/usr/src/linux-4.16.10,右键开终端,还是老规矩,先把权限抢到手:sudo -s
然后,做一些准备工作
更新一些必要的小东西:sudo apt-get update
下载一些必要的组件:

sudo apt-get install libncurses5-dev
sudo apt-get install libssl-dev

清除一些没用的东西:

sudo make mrproper
sudo make clean

打开图形配置界面:

sudo make menuconfig

显示如下:
在这里插入图片描述报错了,怎么说?报错信息里总有能看懂的一句吧?bison not found,它说我没有bison,怎么办,装呗~
apt-get install bison
好,再运行make menuconfig
在这里插入图片描述还报错,flex not found,说我没有flex,怎么办?装呗~
apt-get install flex

再运行make menuconfig,诶!好了~
在这里插入图片描述进到这个蓝色的框框之后,啥也不干,直接Save
在这里插入图片描述然后OK,然后exit就行了,主要是要生成这个.config文件,让这个图形界面把配置全部设置为默认配置就行了,免得后面编译它又要在控制台里问一堆我看不懂也不想看的问题。

b.编译

很简单的一条命令就解决了:sudo make -j4
但是有一点要说,这里的参数 “-j4”,这个"4",就是说让虚拟机用处理器里的4个核一起来做这个编译工作,那肯定比sudo make要快,这也是为什么我要在“创建虚拟机-自定义硬件”这一步时配置4个核的原因。
当然,你电脑要是好得离谱,你给虚拟机搞6个、8个核,有问题吗?没问题~无非让我看着眼馋罢了
等等呗~电脑好就快,一般的电脑,这个命令要执行15–30分钟的样子吧,看个电影,泡个茶,出去活动活动,回来直接看成果。

7.安装内核

很简单的两条命令:
sudo make modules_install
sudo make install
在这里插入图片描述在这里插入图片描述好啦!任务基本完成!现在来看看咱们虚拟机的内核版本:
uname -a

在这里插入图片描述哟~怎么还是4.4.0.21?没重启呗,重启再来
在这里插入图片描述不就好了嘛~linux4.16.10这不就装上去了

8.测试

写个测试程序,看看对不对:
↓↓↓↓↓↓ test_syscall.c ↓↓↓↓↓↓
在这里插入图片描述

Q:诶诶诶!这385哪来的啊!
A:系统调用登记那一步,那个什么什么系统调用号,让你记着你不记!吃我一巴掌pia~

建个文件,source.txt,随便写点东西进去:
↓↓↓↓↓↓ source.txt ↓↓↓↓↓↓
在这里插入图片描述编译test_syscall.c:gcc -g test_syscall.c -o test_syscall
运行test_syscall:./test_syscall
运行结果:
在这里插入图片描述

代码在这:

#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>

#define SYS_FILECOPY 385

int main(){
	const char *srcFile = "source.txt", *dstFile = "destination.txt";
	syscall(SYS_FILECOPY, srcFile, dstFile);
	return 0;
}

结束了~
如果出现了上面没包含的错误可以QQ私戳我,万一我看懂了呢~
反正是小号,随便加!
QQ:1708297467

参考了下面这些大佬的文章!!
Linux编译内核及添加系统调用

make menuconfig错误: /bin/sh: 1: flex: not found 和 /bin/sh: 1: bison: not found

make: *** No rule to make target `menuconfig’. Stop.问题解决方案-Linux(3)

Linux 内核编译(三天吐血经历!)

在Ubuntu下,编译Kernel报错:Makefile:xxx: recipe for target ‘xxx’ failed

Logo

更多推荐