实验截图
将menu文件夹中的test.c文件的main函数部分加入自己的系统调用,如上图中的红框所示。
将自己写的系统调用函数写入test.c文件中,如上图所示。
在MenuOS中运行自己的系统调用命令,fork命令,效果如上图所示。
从system_call到iret的伪代码分析
ENTRY(system_call)
SAVE_ALL //保护现场
syscall_call:
call *sys_call_table(,%eax,4) //在系统调用表中查找并调用系统调用函数
syscall_after_call:
movl %eax,PT_EAX(%esp) //保存返回值
syscall_exit:
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work //检测需不需要进行额外的工作。
restore_all: //恢复现场
TRACE_IRQS_IRET
irq_return: //回到用户态
INTERRUPT_RETURN
END(syscall_exit_work)
work_pending:
test $_TIF_WORK_SYSCALL_EXIT,%ecx
jz work_pending
END(syscall_exit_work)
work_pending: //处理信号
testb $_TIF_NEED_RESCHED,%c1
jz work_notifysig
work_resched: //重新调度
call schedule
jz restore_all //返回系统调用
work_notifysig:
...
END(work_pending)
system_call到iret的简要流程图
总结
系统调用处理过程:当程序执行到int 0x80语句时进入系统调用,首先做的事是保存现场,即进入中断程序保存需要用到的寄存器的数据。然后从eax中取出系统调用号在sys_call_table这个表中查找对应的系统调用函数并执行,执行完后保存返回值。检查是否需要进行其他工作,如进程间通信,重新调度等等,如需要则进行其他工作,工作完成后恢复现场,即退出中断程序,恢复原来保存的数据到寄存器中,如不需要,则直接恢复现场,回到用户态。
Sawoom原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000