为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;
-
}
运行结果:
用户层
内核层
本文出自 “牛哥的博客” 博客