内核驱动开发第五天linux系统调用

1.系统调用
一般情况下,用户进程是不能访问内核的。它既不能访问内核中的数据,也不能调用内核中的函数。但系统调用是一个例外。还有一个是中断
Linux内核中设置了一组用于实现各
种系统功能的子程序,称为系统调
用。用户可以通过系统调用命令在自
己的应用程序中调用它们。


2.区别
系统调用和普通的函数调用非常相
似,区别仅仅在于,系统调用由操作
系统内核实现,运行于内核态;而普
通的函数调用由函数库或用户自己提
供,运行于用户态。
3.库函数
Linux系统还提供了一些C语言函数
库,这些库对系统调用进行了一些包
装和扩展,这些库函数与系统调用的
关系非常紧密
4.系统调用数
在2.6.29 版内核中,共有系统调用332个,可
在arch/arm/include/asm/unistd.h中找到它
们。
5.使用系统调用
#include<time.h>

main()
{

time_t the_time;


the_time=time((time_t *)0); /*调用time系统调用*/

printf("The time is %ld\n",the_time);

}

/* 从格林尼治时间1970年1月1日0:00开始到现在的秒数。 */


6.工作原理
一般情况下,用户进程是不能访问内核的。它既不能访
问内核所在的内存空间,也不能调用内核中的函数。系
统调用是一个例外。


其原理是进程先用适当的值填充寄
存器,然后调用一个特殊的指令,这个指令会让用户程
序跳转到一个事先定义好的内核中的一个位置,内核根据应用程序所填充的固定值来找到相应的函数执行。
1.适当的值
在文件include/asm/unistd.h中为每一个系统调用规定了唯一的编号,这个号码称为系统调用号
  #define__NR_restart_syscall  (__NR_SYSCALL_BASE+0)
2.特殊的指令
v 在Intel CPU中,这个指令由中断0x80实现。


v 在ARM中,这个指令是SWI
指令(已经重命名为SVC指令)
3.固定的位置(在arm中)
ENTRY(vector_swi) <entry-common.S>。

4.相应的函数
上面过程检查系统调用号,这个号码告诉内
核进程请求哪种服务。然后,它查看系统
调用表(sys_call_table)找到所调用的内核
函数入口地址。接着,就调用函数,等返
回后,做一些系统检查,最后返回到进
程。







/* arch/arm/kernel/calls.S */


/* 0 */


CALL(sys_restart_syscall)

CALL(sys_exit)

CALL(sys_fork_wrapper)

CALL(sys_read)

CALL(sys_write)

/* 5 */
CALL(sys_open)
...... ...... ...... ...... ...... ...... ...... ...... ...... ...... ......

CALL(sys_dup3)


CALL(sys_pipe2)


/* 360 */
CALL(sys_inotify_init1)


具体流程
1.

#define __syscall(name) "swi\t" __NR_##name "\n\t“


int open( const char * pathname, int flags)


{
。。。。。。

__syscall(open);

。。。。。。

}


转化为


int open( const char * pathname, int flags)
{
。。。。。。

swi\t __NR_open

。。。。。。


}




2.
/* arch/arm/kernel/entry-common.S */

ENTRY(vector_swi)

......
..
....
....
..
......

adr tbl, sys_call_table

......
..
....
....
..
......

ldrcc pc, [tbl, scno, lsl #2]

......
......
......

@ load syscall table pointer

@ call sys_* routine


......

ENTRY(sys_call_table)

#include "calls.S"
3.





/* arch/arm/kernel/calls.S */


/* 0 */


CALL(sys_restart_syscall)

CALL(sys_exit)

CALL(sys_fork_wrapper)

CALL(sys_read)

CALL(sys_write)

/* 5 */
CALL(sys_open)
...... ...... ...... ...... ...... ...... ...... ...... ...... ...... ......

CALL(sys_dup3)


CALL(sys_pipe2)


/* 360 */
CALL(sys_inotify_init1)

/*************************************************
**************************************************/
通过反汇编c库来查看具体的系统调用过程
arm-linux-objdump -D -S libc.so.6 >log
通过分析反汇编的文件来查看具体的系统调用
/*************************************************
**************************************************/
7.实现系统调用


向内核中添加新的系统调用,需要执行 3
个步骤:

1. 添加新的内核函数

2. 更新头文件 unistd.h

3. 针对这个新函数更新系统调用表
calls.S

实现系统调用


1. 在kernel/sys.c中添加函数:

asmlinkage int sysMul(int a, int b)

{
int c;
c = a*b;
return c;
}
/*asmlinkage 使用锥栈进行参数传递*/
2. 在arch/arm/include/asm/unistd.h中添
加如下代码:


#define __NR_sysMul 361

3.在arch/arm/kernel/calls.S中添加代
码,指向新实现的系统调用函数:


CALL(sysMul)
8.调用方式
#include <stdio.h>

#include <linux/unistd.h>

main()


{

int result;

result =
syscall(361,1, 2);//调用系统调用

printf("result = ", result);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值