- 实验题目:linux内核编及添加系统调用
- 添加一个系统调用,实现对指定进程的 nice 值的修改或读取功能,并返回进程最新的 nice 值及优先级 prio。建议调用原型为:
int mysetnice(pid_t pid, int flag, int nicevalue, void __user * prio, void __user * nice); 参数含义:
pid:进程 ID。
flag:若值为 0,表示读取 nice 值;若值为 1,表示修改 nice 值。
Prio、nice:进程当前优先级及 nice 值。
返回值:系统调用成功时返回 0,失败时返回错误码 EFAULT。
- 写一个简单的应用程序测试(1)中添加的系统调用。
- 若程序中调用了 linux 的内核函数,要求深入阅读相关函数源码。
- 项目实现过程
安装ubuntu的时候,编译出错
原因:没有安装 ncurses 包
解决方法:#apt-get install libncurses5-dev
- 编写SYSCALL_DEFINEx()函数时,参数用法错误,函数命名不规范
解决方法:
以传统参数命名,应该是 类型 参数名(例如:int a),但是linux存在宏定义,而且用强制转化,把所有的32位参数声明为long,然后再强制转化成实际的类型,比如int。因此参数类型和参数名之间要加上逗号。(具体可参考链接:http://blog.chinaunix.net/uid-9185047-id-445212.html)
SYSCALL_DEFINEx里面的x代表的是系统调用参数个数,在本题中,用到的参数有pid,flag,nicevalue三个,因此x=3;
- 输出函数的问题
解决方法:内核中的输出函数应该是printk而不是printf,因为内核中没有printf的头文件,printf运行在用户态,printk运行在内核态。
- 程序完整代码
测试函数:
//test.c
#include<linux/unistd.h>
#include<sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
#define __NR_mysetnice 333
int main(int argc, char *argv[])
{
pid_t tid;
int nicevalue;
tid = getpid();
int nice;
printf("Please input nicevalue:(MAX_NICE=19;MIN_NICE=-20)\n");
scanf("%d",&nice);
syscall(333,tid,0,0);//read
syscall(333,tid,1,nice);//set
syscall(333,tid,0,0);//read
return 0;
}
系统调用函数/*修改 linux-4.12/kernel/sys.c*/
SYSCALL_DEFINE3(ljhsyscall,pid_t,pid,int,flag,int,nicevalue){
struct pid * kpid;
struct task_struct * task;
int nicebef,priovalue;/*当前nice值以及当前优先级*/
kpid = find_get_pid(pid);/* 返回pid */
task = pid_task(kpid, PIDTYPE_PID);/* 返回task_struct */
nicebef = task_nice(task);/* 返回进程当前nice值 */
if(flag == 1)
{
set_user_nice(task, nicevalue);/* 修改进程nice值 */
priovalue = NICE_TO_PRIO(nicevalue);/*调用NICE_TO_PRIO函数*/
printk("该进程的nice值为:%d\t 该进程的prio值为: %d\n", nicevalue, priovalue);
return 0;
}
else if(flag == 0)
{
priovalue = NICE_TO_PRIO(nicebef);
printk("该进程的nice值为:%d\t 该进程的prio值为: %d\n", nicebef, priovalue);
return 0;
}
return EFAULT;
}