本文主要是介绍linux内核系统调用与应用层接口的概念以及linux内核层与应用层之间的关系。
一、系统调用接口与应用层接口的关系
1.1 glibc介绍
glibc即为GNU C LIBRARY,为linux系统的应用层最底层的调用接口,glibc作为应用层的系统调用接口与Linux内核进行通信,而glibc库对上层应用提供基于posix标准以及基于system V标准的接口等。
1.2 Libstdc++介绍
Libstdc++是c++相关的接口函数,其不直接与linux系统调用接口交互,其主要调用glibc提供的应用接口。
1.3 系统调用与应用层接口的关系
系统调用接口是linux内核提供的接口,其并不属于应用层程序,应用层的系统库接口glibc,通过对系统调用的封装,向应用程序提供基于posix标准的(如内存申请与释放相关的接口malloc、free等)。
如下图所示,即为应用层系统库glibc、应用程序、linux内核各模块之间的关系,其中应用程序及库函数通过系统调用接口调用内核层的各子模块。
![0fed14c906ee270e085ce6018ecddb0a.png](https://img-blog.csdnimg.cn/img_convert/0fed14c906ee270e085ce6018ecddb0a.png)
那glibc是如何调用系统调用接口的吗?以arm架构cpu为例,其通过swi(软中断)从用户空间进入内核空间。调用系统调用接口。下面以应用接口open函数为例进行介绍。
![2f448952bea71b1add1754a21dfc0a1c.png](https://img-blog.csdnimg.cn/img_convert/2f448952bea71b1add1754a21dfc0a1c.png)
glibc中open接口的调用流程图如下,该接口最终通过调用INLINE_SYSCALL,实现调用内核的open接口。而INLINE_SYSCALL最终调用INTERNAL_SYSCALL_RAW进行LINUX内核的系统调用接口,该宏定义主要是通过 SWI指令,使CPU进入软中断处理流程,LINUX内核的软中断处理接口通过传入r7寄存器的数值,确定调用的系统接口。
#define INLINE_SYSCALL(name, nr, args...)
({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))
{
__set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));
_sys_result = (unsigned int) -1;
}
(int) _sys_result; })
# define INTERNAL_SYSCALL_RAW(name, err, nr, args...)
({
register int _a1 asm ("r0"), _nr asm ("r7");
LOAD_ARGS_##nr (args)
_nr = name;
asm volatile ("swi 0x0 @ syscall " #name
: "=r" (_a1)
: "r" (_nr) ASM_ARGS_##nr
: "memory");
_a1; })
通过swi指令,使cpu进入svc特权模式,然后linux内核根据传入r7寄存器的值(即为__NR_openat unistd.h),确认系统调用的类型(并以r0-r6中存储的变量作为入参)。
此处只是简要说明系统调用与应用层glibc库的关系,关于内核层vfs相关的内容,会在后续作为单独的章节说明。