Linux3.18.6内核添加系统调用(32位系统)

1.将已经下载好的内核解压,我的目录是

/home/shangsongchao/LinuxKernel/testlinux-3.18.6/linux-3.18.6

 2.添加系统调用表:

在/home/shangsongchao/LinuxKernel/testlinux-3.18.6/linux-3.18.6/arch/x86/syscalls目录下,打开syscall_32.tbl

添加三个系统调用,如图358,359,360

 不需要像Linux 2.6的内核一样,在<asm/unistd.h>中添加类似于#define __NR_foo 358之类的宏定义了,3.x的内核会自动根据系统调用表的定义生成。

3.添加系统调用的服务例程

在/home/shangsongchao/LinuxKernel/testlinux-3.18.6/linux-3.18.6/arch/x86/kernel目录下,打开process_32.c

添加下面函数

/*
 * sys_foo 
 * return each process kernel stack sizes
 * */
asmlinkage long sys_foo(void)
{
	return 5;
}

/*
 * sys_my_oper
 * compute numbers + - * /
 */
asmlinkage long sys_my_oper(int * result , int num1,int num2, char *op)
{
	if(*op=='+')
	{
		*result=num1+num2;
	}
	else if(*op=='-')
	{
		*result=num1-num2;
	}
	else if(*op=='*')
	{
		*result=num1*num2;
	}
	else if(*op=='/')
	{
		*result=num1/num2;
	}
	else
		return 0;
	return 0;
}

/*
 * sys_my_compute
 * compute numbers + - * /
 */
asmlinkage long sys_my_compute(int num1,int num2, char *op)
{
	long result=0;

	if(*op=='+')
	{
		result=num1+num2;
	}
	else if(*op=='-')
	{
		result=num1-num2;
	}
	else if(*op=='*')
	{
		result=num1*num2;
	}

	else if(*op=='/')
	{
		result=num1/num2;
	}
	else
		result=0;
	return result;
}

 如图:

4.编译内核

在/home/shangsongchao/LinuxKernel/testlinux-3.18.6/linux-3.18.6目录下,执行一下命令:

make i386_defconfig
make # 一般要编译很长时间,少则20分钟多则数小时

 5.安装内核

 sudo make modules  //编译模块
 sudo make modules_install //安装模块
 sudo make install  //安装内核

 6.重启查看内核版本

uname -r

 7.编写C测试程序

#include<linux/unistd.h>
#include<sys/syscall.h>
#include<stdio.h>
#include <time.h>
#define _NR_my_oper 359
#define CALL_TIME 1000*1000*100
int main(){

	int num1 = 10;
	int num2 = 5;
	int result;
	long i;
	time_t *t;
	long end;
	long begin = (long)(time(t));

	for(i =0; i<CALL_TIME ;i++ ){
		syscall(_NR_my_oper, &result, num1, num2, "+");
	}
	printf("%d\n",result);

	end = (long)(time(t));
	printf("syscall:%ld\n", end-begin);
	begin = (long)(time(t));

	for(i =0; i<CALL_TIME ;i++ ){
		result = num1+num2;
	}

	printf("%d\n",result);
	end = (long)(time(t));
	printf("non-syscall:%ld\n", end-begin);

	return 0;
}

 测试图

 

收获:

1. 系统调用表的产生过程。
内核开发者是在syscall_64.tbl中声明系统调用号与服务例程的对应关系,以及其ABI,但系统调用表的真正定义是在arch/x86 /kernel/syscall_64.c中。

① arch/x86/kernel/syscall_64.c, arch/x86/kernel /syscall_32.c文件中存放了实际的系统调用表定义,以64位系统为例,其中有如下内容:

#include <asm/asm-offsets.h>

#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)

#ifdef CONFIG_X86_X32_ABI
# define __SYSCALL_X32(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
#else
# define __SYSCALL_X32(nr, sym, compat) /* nothing */
#endif

#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ; // 注意,是分号结尾
#include <asm/syscalls_64.h> // 引入系统调用服务例程的声明
#undef __SYSCALL_64

#define __SYSCALL_64(nr, sym, compat) [nr] = sym, //注意,是逗号结尾

typedef void (*sys_call_ptr_t)(void);

extern void sys_ni_syscall(void);

const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { //系统调用表定义
        /*
         * Smells like a compiler bug -- it doesn't work
         * when the & below is removed.
         */
        [0 ... __NR_syscall_max] = &sys_ni_syscall,
#include <asm/syscalls_64.h> // 系统调用服务例程地址,对应arch/x86/include/generated/asm/syscalls_64.h文件
};

 

② arch/x86/syscalls目录中的syscall_64.tbl、syscall_32.tbl文件是系统调用表声明。syscalltbl.sh脚本负责生产syscalls_XX.h文件,由Makefile负责驱动
② arch/x86/include/generated目录,其中存放根据arch/x86/syscalls目录生成的文件。主要有 generated/asm/syscalls_64.h、generated/asm/syscalls_32.h文件,用于生成系统调用表数组。生成 的syscalls_32.h内容部分如下:

 

2. 系统调用号声明头文件的生成(#define __NR_xxx之类的信息)。

类似于系统调用表的产生,arch/x86/syscalls/syscallhdr.sh脚本负责generated/uapi/asm /unistd_32.h, generated/uapi/asm/unistd_64.h文件,unistd_XX.h文件又被间接include到 asm/unistd.h中,后者最终被include用户空间使用的<sys/syscall.h>文件中(安装之后)。生成的generated/uapi/asm/unistd_32.h部分内容如下

 
 

注意,这里的unistd.h文件与用户空间使用的<unistd.h>文件没有任何关系,后者声明了系统调用包装函数,包括syscall函数等

参考网址:

http://www.myext.cn/other/a_16300.html

转载于:https://www.cnblogs.com/pingandezhufu/p/4575132.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值