现在的位置: 首页 >> 操作系统 >> FreeBSD >> FreeBSD 5内核源代码分析之系统调用过程
添加时间:2005-8-21 来源:网教中国 作者:
FreeBSD 5内核源代码分析之系统调用过程


对照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, &params);

如果该进程有自己的系统调用准备函数,则调用之。事实上,所谓的系统调用准备函数,
其作用应该就是对用户传进来的参数进行解释。如果没有准备函数,则内核做缺省处理,如下:

代码:

} 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中了。

代码:

上一页 [1] [2] [3] [4]  下一页


上一篇:FreeBSD 5内核源代码分析之copyin()实现原理 下一篇:FreeBSD 5 内核源代码分析之中断处理
大部分文章摘自网上,如有侵犯您的权益请与我们联系,我们会第一时间进行处理,谢谢! [ 打印文章 ] [ 关闭窗口 ]
推荐文章
·FreeBSD handbook中文版 9 配制F
·FreeBSD 升级系统
·Ports & Package
·FreeBSD kernel 编译大法(二)ker
·FreeBSD 上使用Kerberos 5认证
·FreeBSD 5.x 中 gbfs 的修正,及
·FreeBSD 安装Linuxigd
·FreeBSD 使用cvsd创建安全的cvs
·FreeBSD trafcount命令介绍
·FreeBSD入门安装及汉化
相关文章
·FreeBSD 5内核源代码分析之copyi
最新文章
·FreeBSD连载(94):基于NAT的负载
·FreeBSD连载(93):反向代理负载
·FreeBSD连载(92):基于DNS的负载
·FreeBSD连载(91):提升静态网页
·FreeBSD连载(90):单服务器性能
·FreeBSD连载(89):CGI和SSI的安
·FreeBSD连载(88):安全连接方式S
·FreeBSD连载(87):基于用户的访
·FreeBSD连载(86):对IP地址和域
·FreeBSD连载(85):配置Apache服(
Google