|
|
|
| |
添加时间:2005-8-21 来源:网教中国 作者: |
|
|
|
|
|
对照struct trapframe又可知,此时syscall(frame)的参数在堆栈上已经构造好。
| 代码: |
mov $KDSEL,%ax /* switch to kernel segments */
mov %ax,%ds
mov %ax,%es
mov $KPSEL,%ax
mov %ax,%fs
|
切换到内核数据段,并将%fs设置好,%fs指向一个per cpu的段,内存CPU相关的数据,
比如当前线程的pcb和struct thread指针。
| 代码: |
FAKE_MCOUNT(13*4(%esp))
call syscall
MEXITCOUNT
jmp doreti
|
调用syscall()函数。syscall()返回后,
将转到doreti(也在sys/i386/i386/exception.s中),判断是否可以执行AST,
最后结束整个系统调用。
3,syscall()函数
---------------
我们接着看syscall()函数
| 代码: |
/*
* syscall - system call request C handler
*
* A system call is essentially treated as a trap.
*/
void
syscall(frame)
struct trapframe frame;
{
caddr_t params;
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
register_t orig_tf_eflags;
u_int sticks;
int error;
int narg;
int args[8];
u_int code;
/*
* note: PCPU_LAZY_INC() can only be used if we can afford
* occassional inaccuracy in the count.
*/
PCPU_LAZY_INC(cnt.v_syscall);
#ifdef DIAGNOSTIC
if (ISPL(frame.tf_cs) != SEL_UPL) {
mtx_lock(&Giant); /* try to stabilize the system XXX */
panic("syscall");
/* NOT REACHED */
mtx_unlock(&Giant);
}
#endif
sticks = td->td_sticks;
td->td_frame = &frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
|
如果进程的user credential发生了改变,更新线程的相应指针。
| 代码: |
if (p->p_flag & P_SA)
thread_user_enter(p, td);
|
如果进程的线程模型采用scheduler activation,则需要通知用户态的线程manager
(FIXME)
| 代码: |
(sys/sys/proc.h)
#define P_SA 0x08000 /* Using scheduler activations. */
|
| 代码: |
params = (caddr_t)frame.tf_esp + sizeof(int);
code = frame.tf_eax;
|
params指向用户传递的系统调用参数。code指示是何种系统调用,后面还有描述。
| 代码: |
orig_tf_eflags = frame.tf_eflags;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
(*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms);
|
如果该进程有自己的系统调用准备函数,则调用之。事实上,所谓的系统调用准备函数,
其作用应该就是对用户传进来的参数进行解释。如果没有准备函数,则内核做缺省处理,如下:
| 代码: |
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
* fuword is MP aware.
*/
if (code == SYS_syscall) {
/*
* Code is first argument, followed by actual args.
*/
code = fuword(params);
params += sizeof(int);
} else if (code == SYS___syscall) {
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
*/
code = fuword(params);
params += sizeof(quad_t);
}
}
|
如果该进程没有自己的系统调用准备函数,即缺省情况,则根据系统调用是32位还是64位,
得到相应的具体系统号,并相应调整指向用户参数的指针。
SYS_syscall对应32位方式,
SYS___syscall对应64位方式。
函数fuword()意为fetch user word,即从用户空间拷贝一个word到内核空间来。其定义在
sys/i386/i386/support.s中,其实现与copyin()类似,我们略过。
此时,具体的系统调用号已经在变量code中了。
| 大部分文章摘自网上,如有侵犯您的权益请与我们联系,我们会第一时间进行处理,谢谢! |
[ 打印文章 ] [ 关闭窗口 ] |
|