知识背景:
一.SWI:软中断指令, 可以从用户空间切换到系统空间。
以用户空间的read函数操做流程分析:
1.用户空间的read调用会对应一个内核空间的read调用。
2.从用户空间切换到内核空间需要用到一个指令SWI。
3.切换到内核空间之后会取相对应的系统调用的编号,这个编号是随SWI指令传进来的。
4.在内核里面会维护一张系统调用表,表中的每个系统调用对应一个系统编号。
二.ENTRY(vector_swi)在entry_common.S文件中。
三.用户空间总是将系统编号放进R7当中,然后内核会通过调用SWI指令将系统切换到内核态,然后将R7中的系统编号取出放入scno中,
然后内核会根据scno的值从系统调用表中取出相对应的系统调用。
实验步骤:
一.比如写类似printk函数功能的函数。在kernel文件夹里面的printk.c里面写
例如:
void sys_pk() { printk("this is a new sys_call!\n"); }
二.然后修改calls.s(/arch/arm/kernel)在最后面修改
三.然后在Unistd.h(/arch/arm/include/asm)做和在calls.s一样的修改。
代码分析:
在entry_common.S中会有一行代码ENTRY(vector_swi),这部分代码是内核专门用来响应SWI指令,如下:
#elif defined(CONFIG_ARM_THUMB) /* Legacy ABI only, possibly thumb mode. */ tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in ldreq scno, [lr, #-4] #else /* Legacy ABI only. */ ldr scno, [lr, #-4] @ get SWI instruction A710( and ip, scno, #0x0f000000 @ check for SWI ) A710( teq ip, #0x0f000000 ) A710( bne .Larm710bug ) #endif
在这部分代码中是从R7中取出系统编号,放入在scno,然后从系统调用表中调出相关的系统调用
代码实现为
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
实验结果:自己写系统调用不成功。原因分析:不明??