linux添加系统调用【简单易懂】【含32位系统】【含64位系统】
linux添加系统调用【简单易懂】【含32位系统】【含64位系统】
linux添加系统调用【简单易懂】【含32位系统】【含64位系统】
前言
众口难调,所以干脆,“虚拟机管理软件+虚拟机+内核”,所有步骤都写上去了,友友们可以根据自己的需求翻着看呀~
环境
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这些丑不拉几的函数
用户态函数 | 核态函数 |
---|---|
open | sys_open |
read | sys_read |
write | sys_write |
printf | printk |
参数基本相同,唯一要说的是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)
在Ubuntu下,编译Kernel报错:Makefile:xxx: recipe for target ‘xxx’ failed
更多推荐
所有评论(0)