关于系统调用
以/src/libc/process.c中DEF_SYSCALL(Spawn_Program,SYS_SPAWN,int,
(const char *program,const char *command)
const char *arg0=program;
size_t arg1=strlen(program);
const char*arg2=command;
size_t arg3 *strlen(command);
SYSCALL_REGS_4)为例:
◆DEF_SYSCALL是函数的宏定义,在syscall.h中,定义如下:
#define DEF_SYSCALL(name,num,retType,params,argDefs,regs)
retType name params{
int sysNum=(num),rc;
argDefs
__asm__ __volatile__(SYSCALL:”=a”(rc):”a”(sysNum)regs);
return (retType) rc;
}
◆ 根据此宏定义我们可以写出下面的函数(其中SYSCALL定义为:“int $0x90”,作为系统调用中断号):
int Spawn_Program (const char *program,const char *command)
{
int sysNum=(SYS_SPAWN),rc;
const char *arg0=program;
size_t arg1=strlen(program);
const char*arg2=command;
size_t arg3 *strlen(command);
__asm__ __volatile__(SYSCALL:”=a”(rc):”a”(sysNum) SYSCALL_REGS_4);
return (int) rc;
}
◆在syscall.h中有个系统调用号的枚举类型:
enum{
SYS_NULL,
SYS_EXIT,
SYS_PRINTSTRING,
SYS_GETKEY
SYS_SETATTR,,
SYS_GETCURSOR,
SYS_PUTCURSOR,
SYS_SPAWN,
SYS_WAIT,
SYS_GETPID,
};
◆在syscall.c文件中定义了一个系统调用处理函数的全局表:
Const Syscall g_syscallTable[]={Sys_Null,Sys_Exit,Sys_PrintString,
Sys_GetKey,Sys_SetAttr,Sys_GetCursor,
Sys_PutCursor,Sys_Spawn,Sys_Wait,Sys_GetPID};
◆ 系统调用处理函数(在trap.c文件中)Syscall_Handler定义如下:
Static void Syscall_Handler(struct Interrupt_State *state)
{
uint_t syscallNum=state->eax;
if(syscallNum<0||syscallNum>=g_numSyscalls){
Print(“Illegal system call %d by process %d\n”
syscallNum,g_currentThread->pid);
Exit(-1);
KASSERT(false);
}
state->eax=g_syscallTable[syscallNum](state);
}
◆ 在上面的函数Spawn_Program中
__asm__ __volatile__(SYSCALL:”=a”(rc):”a”(sysNum) SYSCALL_REGS_4);
“SYSCALL”代表进入系统调用中断,进入系统调用处理函数Syscall_Handler,系统调用号“(sysNum)”(此时值是(SYS_SPAWN))存放在寄存器state->eax中,当调用号<0或>=系统调用处理函数全局表项个数时显示出错信息。然后,根据系统调用号
sysNum被赋值(SYS_SPAWN)作为表g_syscallTable[]下标,从而找到通过表
g_syscallTable[syscallNum](state)找到内核处理程序Sys_Spawn(state),在Sys_Spawn函数中调用Spawn函数进行用户进程的创建。创建成功后返回新进程的进程号给state->eax寄存器。