为Linux内核添加系统调用
目标:向内核添加系统调用long get_shed_times(unsigned long * num),程序调用此函数时,将此进程被调度的次数存入num指向的内存单元中,32位整数。
系统环境:CentOS 5.5 32bit + 2.6.18 source code + i386架构
首先在task_struct中添加调度计数变量unsigned long sched_times;
-
include/linux/sched.h -
-
task_struct { -
-
......... -
-
unsigned long sched_times; -
-
.......... -
-
};
在创建新进程时将sched_times初始化为0
-
kernel/fork.c do_fork()函数 -
-
long do_fork(unsigned long clone_flags, -
unsigned long stack_start, -
struct pt_regs *regs, -
unsigned long stack_size, -
int __user *parent_tidptr, -
int __user *child_tidptr) -
{ -
struct task_struct *p; -
int trace = 0; -
struct pid *pid = alloc_pid(); -
long nr; -
............ -
-
p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr); -
p->sched_times = 0; -
................ -
-
}
进程调度时,sched_times ++
-
kernel/sched.c scheduale()函数 -
-
asmlinkage void __sched schedule(void) -
-
{ -
-
........ -
-
idx = sched_find_first_bit(array->bitmap); -
queue = array->queue + idx; -
next = list_entry(queue->next, struct task_struct, run_list); -
next->sched_times ++; -
if (!rt_task(next) && interactive_sleep(next->sleep_type)) { -
unsigned long long delta = now - next->timestamp; -
if (unlikely((long long)(now - next->timestamp) < 0)) -
delta = 0; -
......... -
-
} -
添加系统调用
-
kernel/sys.c 最后边 -
-
asmlinkage long sys_get_sched_times(unsigned long * addr) -
-
{ -
printk(KERN_ALERT "get_sched_times called,sched_times=%d",current->sched_times); -
return copy_to_user(addr,&(current->sched_times),sizeof(long)); -
-
}
添加系统调用号 include/asm/unistd.h
在最后,加入#define __NR_get_sched_times 318,并将NR_syscalls改为319
在文件中arch/i386/kernel/syscall_table.S最后添加如下内容:
OK,重新编译内核,重启。
测试:
通常,系统调用需要靠C库支持。但是,也可以直接用syscall或者用Linux本身提供的宏
宏: __syscalln() n的范围从0到6,代表需要传给系统调用的参数个数,例如open
long open(const char *filename, int flags,int mode);
#define __NR_open 5
__syscall3(long,open,const char*,filename,int,flags,int,mode)
上述方法在2.6.20以后就去掉了,因为有安全漏洞。
直接使用syscall(系统调用号,参数...)
-
-
#include <stdio.h> -
-
int main() -
{ -
unsigned long num; -
int i,x,sum=0; -
-
scanf("%d",&x); -
for(i=0;i<x*100;i++) -
sum = sum +i; -
printf("%d/n",sum); -
-
if(syscall(318,&num)) -
printf("Failed/n"); -
else -
printf("sched_times =%d/n",num); -
return 0; -
}
运行结果:
用户层

内核层

本文出自 “牛哥的博客” 博客




