注:文章共四部分,分别是
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
#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
#update-grub2
#reboot -n
查看内核版本
#uname -a
成功更换内核!
系统调用表
系统调用号 | 32/64/common | 系统调用名称 | 服务例程入口 |
---|---|---|---|
0 | common | read | sys_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
可见系统调用成功执行
注: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类型。
#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个数。
利用内核函数:
由于大致流程与前面相似,这里便不再详述
添加服务例程原型声明
实现系统调用服务例程
编译安装
编写测试程序