赞
踩
本篇说清楚系统调用
读本篇之前建议先读鸿蒙内核源码分析(总目录)工作模式篇.
本篇通过一张图和七段代码详细说明系统调用的整个过程,代码一捅到底,直到汇编层再也捅不下去. 先看图,这里的模式可以理解为空间,因为模式不同运行的栈空间就不一样.
过程解读
● 在应用层main中使用系统调用mq_open(posix标准接口)
● mq_open被封装在库中,这里直接看库里的代码.
● mq_open中调用syscall,将参数传给寄出器 R7,R0~R6
● SVC 0 完成用户模式到内核模式(SVC)的切换
● _osExceptSwiHdl运行在svc模式下.
● PC寄存器直接指向_osExceptSwiHdl处取指令.
● _osExceptSwiHdl是汇编代码,先保存用户模式现场(R0~R12寄存器),并调用OsArmA32SyscallHandle完成系统调用
● OsArmA32SyscallHandle中通过系统调用号(保存在R7寄存器)查询对应的注册函数SYS_mq_open
● SYS_mq_open是本次系统调用的实现函数,完成后return回到OsArmA32SyscallHandle
● OsArmA32SyscallHandle再return回到_osExceptSwiHdl
● _osExceptSwiHdl恢复用户模式现场(R0~R12寄存器)
● 从内核模式(SVC)切回到用户模式,PC寄存器也切回用户现场.
● 由此完成整个系统调用全过程
七段追踪代码,逐个分析
1.应用程序 main
intmain(void)
{
charmqname[NAMESIZE], msgrv1[BUFFER], msgrv2[BUFFER];
const char*msgptr1 ="test message1";
const char*msgptr2 ="test message2 with differnet length";
mqd_t mqdes;
intprio1 = 1, prio2 = 2;
struct timespec ts;
struct mq_attr attr;
intunresolved = 0, failure = 0;
sprintf(mqname, "/"FUNCTION"_"TEST"_%d", getpid());
attr.mq_msgsize = BUFFER;
attr.mq_maxmsg = BUFFER;
mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);
if (mqdes == (mqd_t)-1) {
perror(ERROR_PREFIX "mq_open");
unresolved = 1;
}
if (mq_send(mqdes, msgptr1, strlen(msgptr1), prio1) != 0) {
perror(ERROR_PREFIX "mq_send");
unresolved = 1;
}
printf("Test PASSED\n");
returnPTS_PASS;
}
2. mq_open 发起系统调用
mqd_t mq_open(constchar*name,intflags, ...)
{
mode_t mode = 0;
struct mq_attr *attr = 0;
if (*name=='/')name++;
if (flags & O_CRE
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。