linux驱动开发3系统调用.docx

上传人:b****6 文档编号:15689690 上传时间:2023-07-06 格式:DOCX 页数:13 大小:531.72KB
下载 相关 举报
linux驱动开发3系统调用.docx_第1页
第1页 / 共13页
linux驱动开发3系统调用.docx_第2页
第2页 / 共13页
linux驱动开发3系统调用.docx_第3页
第3页 / 共13页
linux驱动开发3系统调用.docx_第4页
第4页 / 共13页
linux驱动开发3系统调用.docx_第5页
第5页 / 共13页
linux驱动开发3系统调用.docx_第6页
第6页 / 共13页
linux驱动开发3系统调用.docx_第7页
第7页 / 共13页
linux驱动开发3系统调用.docx_第8页
第8页 / 共13页
linux驱动开发3系统调用.docx_第9页
第9页 / 共13页
linux驱动开发3系统调用.docx_第10页
第10页 / 共13页
linux驱动开发3系统调用.docx_第11页
第11页 / 共13页
linux驱动开发3系统调用.docx_第12页
第12页 / 共13页
linux驱动开发3系统调用.docx_第13页
第13页 / 共13页
亲,该文档总共13页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

linux驱动开发3系统调用.docx

《linux驱动开发3系统调用.docx》由会员分享,可在线阅读,更多相关《linux驱动开发3系统调用.docx(13页珍藏版)》请在冰点文库上搜索。

linux驱动开发3系统调用.docx

linux驱动开发3系统调用

一、linux驱动开发--系统调用

1、系统调用原理

用户实现系统调用是通过SWI指令来实现的,SWI指令是使ARM从用户模式切换到管理模式。

内核运行在管理模式,用户模式运行在用户模式。

SWI指令格式如下:

SWI{cond}immed_24

immed_24为24位立即数也就是最终要用的中断号

如执行swi0x900004这条指令就会产生异常,使系统进入到系统管理模式,在异常向量表中的bswi指令,最终会跳转到arch/arm/kernel/entry-common.S这个文件中的vector_swi标号处,

代码如下,做了精简就是程序执行时运行的代码:

.typesys_call_table,#object//定义sys_call_table

ENTRY(sys_call_table)

#include"calls.S"//sys_call_table标号后面直接跟系统调用表,在calls.S中,各个系统调用函数的函数名即函数地址被按顺序存储。

ENTRY(vector_swi)

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

tstr8,#PSR_T_BIT

movner10,#0@nothumbOABIemulation

ldreqr10,[lr,#-4]@getSWIinstruction

//取得SWI指令本身的机器码

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

ldrip,__cr_alignment

ldrip,[ip]

mcrp15,0,ip,c1,c0@updatecontrolregister

#endif

enable_irq

get_thread_infotsk

adrtbl,sys_call_table@loadsyscalltablepointer

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

bicsr10,r10,#0xff000000

//__NR_OABI_SYSCALL_BASE实际为0x900000

所以SWI输入中断号的时候,后面是0x900000加中断号

eornescno,r10,#__NR_OABI_SYSCALL_BASE

sys_oabi_call_table与sys_call_table等价

ldrnetbl,=sys_oabi_call_table

1.//所以对于上面示例中swi0x900004系统调用号scno=0x900004  

2.//eor scno,scno,#0x900000  

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

ldrr10,[tsk,#TI_FLAGS]@checkforsyscalltracing

stmdbsp!

{r4,r5}@pushfifthandsixthargs

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

tstr10,#_TIF_SYSCALL_WORK@arewetracingsyscalls?

bne__sys_trace

cmpscno,#NR_syscalls@checkuppersyscalllimit

adrlr,BSYM(ret_fast_syscall)@returnaddress

ldrccpc,[tbl,scno,lsl#2]@callsys_*routine//找到要调用的函数,开始执行

/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

总之,系统调用就是使用SWI+中断号使系统运行到管理模式,然后再跳转到vector_swi就算出相应的中断号,然后再通过查询sys_call_tabl表,跳转到相应的系统调用函数。

arch/arm/include/asm/unistd.h中定义的都是系统调用号,由用户进程进行系统调用的时候会用到。

2、添加系统调用

1>在 arch/arm/kernel/calls.S中添加自己要添加的系统调用函数如:

asmlinkageintsys_my_add(inta,intb)

{

   returna+b;

}

2>在arch/arm/include/asm/unistd.h中最后一行添加,中断号要最后一个中断号加1

#define__NR_my_ade             (__NR_SYSCALL_BASE+378)

3>arch/arm/kernel/calls.S最后一行添加

       CALL(sys_my_add)

4>在用户空间进行系统调用

#include

#include

#include

intmain(intargc,char*argv[])

{

intsum;

sum=syscall(378,1,2);

printf("sum=%d\n",sum);

return0;

}

3、LR寄存器

ARM异常中断处理、lr寄存器、工作模式栈设计、中断服务程序ISR

中断和异常处理

中断是异常的一种。

每种异常都有各自的异常处理(exceptionhandler),handler存放在异常向量表(vectortable)中,由于向量表比较小,handler里通常通过一句跳转语句跳转到实际的异常服务程序中去。

异常会引起处理器工作模式的变化,异常和工作模式的关系为:

当发生异常时,处理器会自动将:

1.当前模式的cpsr存放至异常模式的spsr

2.pc存放至异常模式的lr

3.改变cpsr的工作模式域

4.将pc设置成exceptionhandler的地址

向量表里面存放着handler,handler里面通常是一句跳转语句:

之所以是跳转语句,是因为这几种异常handler的间隔只有4个字节的地址差,即存放一条32位指令,异常服务程序一条指令处理不完吧,所以放一条跳转语句在那里,通过跳转语句跳转到实际的异常服务程序。

注意B和LDR使用的区别。

然而由于FIQ是向量表里面的最后异常,如果向量表后面没有其他内容的话,FIR的handler可以不用跳转,将FIQ服务程序直接放在地址0x0000001C的开始。

----------------------------

七种异常

reset:

初始化内存、缓存、中断源、每种工作模式下的栈指针。

dataabort:

访问了无效内存地址,譬如某些内存地址上并没有挂载实际的物理器件。

另外,可能访问了没有权限的内存。

IRQ:

外设将IRQ引脚设为低电平时触发。

FIQ:

外设将FIQ引脚设为低电平时触发,FIQ优先级比IRQ高,有更多的独立模式寄存器。

prefetchabort:

取指令时造成内存错误时触发。

SWI:

通过执行SWI指令触发。

undefinedinstruction:

遇到了非法指令。

----------------------------

异常返回

lr寄存器保存着异常返回地址。

几种常用的处理lr的方式

----------------------------

中断

中断处理步骤:

步骤2里面的都是处理器自动完成的,与其他异常有点不太一样的是它还会将中断掩码设为1,即屏蔽中断。

手动使能中断的方法

中断栈设计

中断时需要保护现场,即将当前工作模式下的数据压入栈。

另外,在reset异常中,需要设置栈指针。

为了避免栈溢出,可以每次都调用栈检查函数(见汇编篇),还可以采用内存保护机制。

典型的栈分布为:

B分布比A分布好的原因是,即使栈溢出了,不会损坏向量表。

譬如要设计以上的一个栈分布时,代码如下,不同工作模式下的栈指针应在reset异常下完成:

一开始设置SVC模式的栈,然后IRQ的,然后user的。

通过MSR改变cpsr。

USR_Stack,Usr32md等都是宏定义,通过EQU来定义:

顺便说下DCD指令,DCD就是分配一个地址并初始化为指定的表达式,如:

DCD    0x8000;就是分配一个32位的地址,其内容是0x8000

如果用上标号label,那么这个label相当于一个变量,如:

label  DCD  0X8000;这样引用label就是使用了0x8000这个数值。

----------------------------

简单的非递归的interrupthandler

中断服务程序ISR完成步骤的3和4,在步骤3中通过读取芯片内的中断状态寄存器,可以知道哪个中断源发生了中断,并调用相应的处理程序,所以ISR也像一个表一样的东西。

可以用C编写。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2