linux内核编译及添加系统调用(详细版) 您所在的位置:网站首页 apcut编程系统参数 linux内核编译及添加系统调用(详细版)

linux内核编译及添加系统调用(详细版)

2023-12-04 21:43| 来源: 网络整理| 查看: 265

linux内核编译及添加系统调用

注:文章共四部分,分别是

1、编译更换内核

2、添加一个简单系统系统调用

3、添加读取/修改nice值的系统调用

4、自己设计简单(真的简单)系统调用

注:四个部分结构相似,请根据自身需求自行选择观看。(ps有点唠叨的,但也比较完整),不同内核环境会有差别,使用不同版本可能会产生非预期的错误,如有错误欢迎评论区指出。

相关实验资源: 1、kernel内核源码 https://elixir.bootlin.com/linux/latest/source/include 2、Linux系统版本:Ubuntu16.04 清华源镜像:https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/16.04/ 3、预安装内核linux-4.16.1 清华源镜像:https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-4.16.1.tar.xz

(一)、下载新内核并编译、更换: 第一步:下载解压,进入文件夹 #wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.16.1.tar.xz (或者手动下载压缩包解压) #xz –d linux-4.16.1.tar.xz #tar –xvf linux-4.16.1.tar #cd linux-4.16.1 第二步 :清楚残留的 .config和 .o文件(每次编译出错或者重新编译最好都清理,不清理很占内存) #make mrproper

报错提醒安装ncurses,重新执行make mrproper

#apt-get install libncurses5-dev 第三步:配置内核 #make menuconfig

根据报错提示安装组件,缺啥装啥

#sudo apt install build-essential //安装make和gcc等 #apt-get install libncurses5-dev //安装ncurses-devel #sudo apt-get install flex //安装flex #sudo apt-get install bison //安装bison

没有报错后再执行

#make menuconfig

出现配置的对话框,直接保存(save),文件名也默认.config, 退出。

第四步:编译内核,生成启动映像文件 #make -j4 //-j4是用于加快编译速度。这里我用4线程

报错提示要openssl,安装完再次执行命令即可

#apt-get install libssl-dev 第五步:编译模块

这一步要好久(2-3小时,可能虚拟机配置太低吧)。。。。睡一觉回来就好了

#make modules 第六步:安装内核、模块 安装模块:# make modules_install 安装内核:#make install 第七步:配置 grub 引导程序

只需要执行如下命令:该命令会自动修改 grub

#update-grub2 最后一步重启: #reboot -n

查看内核版本

#uname -a

成功更换内核!

(二)、添加简单系统调用

系统调用表

用于关联系统调用号及其相对应的服务历程入口地址。例如系统调用read在系统调用表中结构如下 系统调用号32/64/common系统调用名称服务例程入口0commonreadsys_read(这里不同内核版本格式有所不同)

path: /arch/x86/entry/syscalls/syscall_64.tbl(32位系统是syscall_32.tbl)

第一步:修改源程序 #cd linux-4.16.1 //进入linux解压包(我下的版本是4.16.1) #vim arch/x86/entry/syscalls/syscall_64.tbl //进入该文件分配系统调用号 (注意别写在最后面,x64的系统调用共300多行,注意别写到后半部分的x32那一块里面)

在这里插入图片描述

#vim include/linux/syscalls.h 进入该文件,添加服务例程的原型声明(shift+g快速跳到最后一行)

vim kernel/sys.c 实现系统调用服务例程

SYSCALL_DEFINE后的数字代表参数个数,这里0个参数(void)

在这里插入图片描述

第二步:编译安装内核 1. #make menuconfig 配置内核 2. #make –j2 编译内核 3. #make modules 编译模块 4. #make modules_install 和 make install 安装模块和安装内核 5. #update-grub2(好像虚拟机不需要这一步) 6. #reboot –n 立即重启 第三步:新系统调用测试

这里编写一个test.c文件来测试(文件存放位置可以任意)

#vim test.c

在这里插入图片描述

编译

gcc test.c -o test //-o test指定编译输出文件名为test

在这里插入图片描述 执行文件

./test

查看信息

dmesg

在这里插入图片描述

可见系统调用成功执行

(三)、添加API对指定进程的 nice 值的读取功能 注:nice值表示进程可被执行的优先级的修正数值,加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。 修改源程序

添加系统调用 在这里插入图片描述 添加系统调用函数声明 在这里插入图片描述 系统调用函数具体代码实现 在这里插入图片描述 代码相关介绍 pid:进程ID flag:等于1表示修改,等于0表示读取 nicevalue:为指定进程设置新的nice值 prio,nice:指向进程当前优先级prio及nice值

copy_to_user函数则是从内核空间拷贝内容到用户空间,用户空间的进程无法直接访问内核空间的内容。

static inline int task_nice(const struct task_struct *p) 用于获取当前task的nice值,并返回nice值,nice值的范围是[ -20 ... 0 ... 19 ] 其使用的例程如下: void set_user_nice(struct task_struct *p, long nice) { bool queued, running; int old_prio, delta; struct rq_flags rf; struct rq *rq; if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE) return; }

return -EFAULT代表返回一个错误代码;

pid_t 其实就是__pid_t类型。(不必在意,找到最原始的定义可能就是个int类型)

#ifndef __pid_t_defined typedef __pid_t pid_t; define __pid_t_defined #endif 编译安装内核 1. #make menuconfig 配置内核 2. #make –j2 编译内核 3. #make modules 编译模块 4. #make modules_install 和 make install 安装模块和安装内核 5. #update-grub2(好像虚拟机不需要这一步) 6. #reboot –n 立即重启

编写测试程序:

#vim test-nice.c //在哪创建没有特别要求

在这里插入图片描述

#gcc nice-test.c -o nice-test //编译,格式gcc -o #./nice-test //执行所生成的文件

在这里插入图片描述

#dmesg //查看信息

在这里插入图片描述

(四)、自己设计系统调用

CONFIG_NR_CPUS是内核被配置支持的CPU个数,而实际设备的CPU个数是在系统启动过程当中去动态监测的。也就是说你配置系统支持32个CPU那么CONFIG_NR_CPUS就等于32,而num_online_cpus()则是当前设备激活可调度的CPU个数。

利用内核函数:

在这里插入图片描述

由于大致流程与前面相似,这里便不再详述

分配系统调用号(335) 在这里插入图片描述

添加服务例程原型声明

在这里插入图片描述

实现系统调用服务例程

在这里插入图片描述

编译安装

#make mrproper#make -j4#make modules#make modules_install#make install#reboot -n

编写测试程序

在这里插入图片描述

编译执行后, dmesg查看信息,如图 在这里插入图片描述 end



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有