继续关于kernel的(1)

编写一个系统调用

关于上一篇文章,按照veriras501学长的博客搭建完kernel环境后,我们现在来尝试编写一个系统调用,实现对指定进程的 nice 值的修改或读取功能,并返 回进程最新的 nice 值及优先级 prio。

成功的方法

这是一个成功的方式,也似乎是一个大部分人都使用的方式

首先,先进入include/linux/syscalls.h内添加以下函数原型
image.png
之后分别进入arch/x86/entry/syscalls/syscall_32.tblarch/x86/entry/syscalls/syscall_64.tbl里添加系统调用号
image.png
ps:这里请一定注意,在syscall_32.tbl里要加上__ia32_,在syscall_64.tbl里要加上__x64_,就像上面那张图一样,不然可能会出现underfined reference to xxx这样的错误。

接下来就是关键的了,在kernel/sys.c里面加上
image.png

之后就make -j8 bzImage然后等他个几分钟

编译完成后写一个demo试试看是否成功
image.png

然后就是制作脚本制作rootfs.img后qemu启动啦
image.png

之后让我们来讲讲这个系统调用吧

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.cMakefile

image.png

按照之前教程修改源码根目录下Makefile文件

image.png

完成日常三大步骤include/linux/syscalls.harch/x86/entry/syscalls/syscall_32.tblarch/x86/entry/syscalls/syscall_64.tbl
image.png
image.png

之后编译内核make -j8 bzImage

依旧写个demo

image.png

然后运行时会出错

image.png
首先就是第一次运行是没有任何回应,第二次运行时有回应了,前面的字符串打印也没什么问题,但是那些数字是不是有那么。。。emmm。。。超级大的问题呢,我传的是20,40,60,80呀。。。这个emmm

大概传参出了问题?

哇,gdb远程也出错QAQ
warning: No executable has been specified and target does not support
wsl
等个大佬救救我QAQ

发布者

Aslin

学习ing~

发表评论

电子邮件地址不会被公开。 必填项已用*标注