编写一个系统调用
关于上一篇文章,按照veriras501学长的博客搭建完kernel环境后,我们现在来尝试编写一个系统调用,实现对指定进程的 nice 值的修改或读取功能,并返 回进程最新的 nice 值及优先级 prio。
成功的方法
这是一个成功的方式,也似乎是一个大部分人都使用的方式
首先,先进入include/linux/syscalls.h
内添加以下函数原型
之后分别进入arch/x86/entry/syscalls/syscall_32.tbl
和arch/x86/entry/syscalls/syscall_64.tbl
里添加系统调用号
ps:这里请一定注意,在syscall_32.tbl
里要加上__ia32_
,在syscall_64.tbl
里要加上__x64_
,就像上面那张图一样,不然可能会出现underfined reference to xxx
这样的错误。
接下来就是关键的了,在kernel/sys.c
里面加上
之后就make -j8 bzImage
然后等他个几分钟
编译完成后写一个demo试试看是否成功
然后就是制作脚本制作rootfs.img后qemu启动啦
之后让我们来讲讲这个系统调用吧
SYSCALL_DEFINE5(lab1, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice) {
struct pid * mypid;
struct task_struct * task;
int nice_before;
int nice_after;
mypid = find_get_pid(pid); //首先,我们在这个地方使用find_get_pid()这个函数获取我们所请求的pid的struct_pid结构体
task = pid_task(mypid, PIDTYPE_PID); //然后我们再通过pid_task()函数来获得pid对应的task_struct结构体,用于task_nice()和set_user_nice()
nice_before = task_nice(task); //获取当前的nice值
if(flag == 1) {
set_user_nice(task, nicevalue); //修改nice值
printk("This is origin nice : %d\nThis is the nice now : %d\n", nice_before, nicevalue);
}
else if(flag == 0) {
printk("The nice is : %d\n", nice_before);
}
/**
copy_to_user(void __user *to, const void *from, unsigned long n)
这三个参数分别是用户内存地址 ,内核空间地址和数据长度
用户内存地址,就使用(int *)prio
内核空间地址,主要关于task_struct结构体,不详讲,用&task_struct
数据长度就是这个prio的长度,sizeof(task_prio)
后面返回nice值也同理
**/
if(copy_to_user((int *)prio, &task->prio, sizeof(task->prio))) {
return EFAULT;
}
nice_after = task_nice(task);
if(copy_to_user((int *)nice, &nice_after, sizeof(nice_after))) {
return EFAULT;
}
return 0;
}
不过似乎还有很多问题。。。当初写的时候并没想到nice值的范围(甚至不知道nice值有范围)。。。
这是一个不知道为什么会出错的方式
最开始,我是想按照网上的一个教程尝试写一个带参数、又和上一个博客写的添加系统调用很相似的方法,
在源码根目录下创建lab1_v2
文件夹,并添加lab1_v2.c
及Makefile
按照之前教程修改源码根目录下Makefile
文件
完成日常三大步骤include/linux/syscalls.h
,arch/x86/entry/syscalls/syscall_32.tbl
和arch/x86/entry/syscalls/syscall_64.tbl
之后编译内核make -j8 bzImage
依旧写个demo
然后运行时会出错
首先就是第一次运行是没有任何回应,第二次运行时有回应了,前面的字符串打印也没什么问题,但是那些数字是不是有那么。。。emmm。。。超级大的问题呢,我传的是20,40,60,80呀。。。这个emmm
大概传参出了问题?
哇,gdb远程也出错QAQ
warning: No executable has been specified and target does not support
wsl
等个大佬救救我QAQ