松下伺服err340(系统调用的实现细节(用户态))

Posted

篇首语:如果终止了学习,人就结束了成长的进步。本文由小常识网(cha138.com)小编为大家整理,主要介绍了松下伺服err340(系统调用的实现细节(用户态))相关的知识,希望对你有一定的参考价值。

松下伺服err340(系统调用的实现细节(用户态))

该文档以一个具体的事例来描述系统调用的细节。本文档的事例在Ubuntu 14.04.4 LTS环境,CPU架构为x86_64,glibc版本为RELEASE = development,VERSION = 2.26.9000。

假如我们写了一个应用程序test.c如下所示:



fork的函数申明在/usr/include/unistd.h头文件中,如下所示:



我们知道gcc会在编译完成test.c后,然后链接libc.so动态库中的fork,所以fork的实现就在glibc代码中,下载glibc源代码,然而glibc中并没有找到fork()的实现。


所以先做一个小实验:编译test.c,然后静态链接libc.a,生成test,然后


反汇编可执行文件test,查看test.s

部分如下内容:



看到main函数实际调用的是__libc_fork。

__libc_fork实现在glibc工程sysdeps/nptl/fork.c路径下,代码略长,此处省略。

但是我们的应用程序调用fork的,是怎么链接到__libc_fork的?在__libc_fork实现下方有如下代码:



__weak_alias实现在glibc工程include/libc-symbols.h路径下,如下:



现在,我们来看看__libc_fork函数,它调用系统功能的代码如下:



可以看出是通过调用ARCH_FROK宏实现调用系统功能的。

该宏在glibc工程sysdeps/unix/sysv/linux/x86_64/arch-fork.h目录下,如下代码所示:



可以看出是通过INLINE_SYSCALL宏调用,传递的参数是clone,该宏在glibc工程sysdeps/unix/sysv/linux/x86_64/sysdep.h头文件定义,与体系结构相关,代码如下:



其中INTERNAL_SYSCALL定义在同文件中,代码如下:



SYS_ify宏定义,代码如下:



__NR_##syscall_name定义在ubuntu系统的/usr/include/x86_64-linux-gnu/asm/unistd_64.h文件中,它是系统调用具体调用系统函数的参数,它是一个编号,比如我们的fork系统调用,它实际通过__NR_clone标号传参,它的定义如下:

#define __NR_clone 56

其中internal_syscall##nr相关的宏在glibc工程sysdeps/unix/sysv/linux/x86_64/sysdep.h定义,如下:

239 #undef internal_syscall0240 #define internal_syscall0(number, err, dummy...)            \\241 (                                  \\242     unsigned long int resultvar;                    \\243     asm volatile (                          \\244     "syscall\\n\\t"                           \\245     : "=a" (resultvar)                          \\246     : "0" (number)                          \\247     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\248     (long int) resultvar;                       \\249 )250 251 #undef internal_syscall1252 #define internal_syscall1(number, err, arg1)                \\253 (                                  \\254     unsigned long int resultvar;                    \\255     TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \\256     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \\257     asm volatile (                          \\258     "syscall\\n\\t"                           \\259     : "=a" (resultvar)                          \\260     : "0" (number), "r" (_a1)                       \\261     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\262     (long int) resultvar;                       \\263 )264 265 #undef internal_syscall2266 #define internal_syscall2(number, err, arg1, arg2)          \\267 (                                  \\268     unsigned long int resultvar;                    \\269     TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \\270     TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \\271     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \\272     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \\273     asm volatile (                          \\274     "syscall\\n\\t"                           \\275     : "=a" (resultvar)                          \\276     : "0" (number), "r" (_a1), "r" (_a2)                \\277     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\278     (long int) resultvar;                       \\279 )280281 #undef internal_syscall3282 #define internal_syscall3(number, err, arg1, arg2, arg3)        \\283 (                                  \\284     unsigned long int resultvar;                    \\285     TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \\286     TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \\287     TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \\288     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \\289     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \\290     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \\291     asm volatile (                          \\292     "syscall\\n\\t"                           \\293     : "=a" (resultvar)                          \\294     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3)         \\295     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\296     (long int) resultvar;                       \\297 )299 #undef internal_syscall4300 #define internal_syscall4(number, err, arg1, arg2, arg3, arg4)      \\301 (                                  \\302     unsigned long int resultvar;                    \\303     TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \\304     TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \\305     TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \\306     TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \\307     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \\308     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \\309     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \\310     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \\311     asm volatile (                          \\312     "syscall\\n\\t"                           \\313     : "=a" (resultvar)                          \\314     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)      \\315     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\316     (long int) resultvar;                       \\317 )318 319 #undef internal_syscall5320 #define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5)    \\321 (                                  \\322     unsigned long int resultvar;                    \\323     TYPEFY (arg5, __arg5) = ARGIFY (arg5);              \\324     TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \\325     TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \\326     TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \\327     TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \\328     register TYPEFY (arg5, _a5) asm ("r8") = __arg5;            \\329     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \\330     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \\331     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \\332     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \\333     asm volatile (                          \\334     "syscall\\n\\t"                           \\335     : "=a" (resultvar)                          \\336     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),     \\337       "r" (_a5)                             \\338     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\339     (long int) resultvar;                       \\340 )341 342 #undef internal_syscall6343 #define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \\344 (                                  \\345     unsigned long int resultvar;                    \\346     TYPEFY (arg6, __arg6) = ARGIFY (arg6);              \\347     TYPEFY (arg5, __arg5) = ARGIFY (arg5);              \\348     TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \\349     TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \\350     TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \\351     TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \\352     register TYPEFY (arg6, _a6) asm ("r9") = __arg6;            \\353     register TYPEFY (arg5, _a5) asm ("r8") = __arg5;            \\354     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \\355     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \\356     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \\357     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \\358     asm volatile (                          \\359     "syscall\\n\\t"                           \\360     : "=a" (resultvar)                          \\361     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),     \\362       "r" (_a5), "r" (_a6)                      \\363     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \\364     (long int) resultvar;                       \\365 )

可以看出internal_syscall##nr宏的number是每个系统调用内核中的入口函数向量地址,通过汇编syscall指令,实现系统调用,从用户态到核心态。


其他体系架构的系统调用基本是这个流程,但从用户态到核心态的汇编指令各不相同,如下:


本人水平有限,欢迎大家指正批评,欢迎私信联系我。

相关参考