glibc源码分析之系统调用(一)

本文详细介绍了glibc如何封装系统调用,重点分析了i386架构下Linux操作系统的封装过程。通过make-syscall.sh、syscall-template.S和syscalls.list文件,解释了如何生成.S文件并结合syscall-template.S完成系统调用的封装。以chdir系统调用为例,解析了汇编代码和相关宏定义,展示了系统调用错误处理和参数传递的细节。
摘要由CSDN通过智能技术生成

在编写本文时,glibc的最新版本是glibc-2.26。本文所有描述都是基于glibc-2.26。
系统调用
系统调用是程序员接触到的最底层的构建程序的组件。它们由内核实现,提供给程序调用。用户按照其调用规则可以实现调用。
glibc的封装方式
glibc使用了两种方式来封装系统调用。一种是由脚本生成。一种是.c文件。
使用.c文件封装系统调用,是因为封装过程比较复杂,除了按系统调用的调用规则来封装外,还要进行其他处理。而脚本生成则十分简单。只要按照系统调用的调用规则来封装即可。由于系统调用的调用规则相对简单且有相似性。所以glibc使用脚本生成封装文件。
脚本封装涉及了三种不同类型的文件。一,make-syscall.sh文件。二,syscall-template.S文件。三,syscalls.list文件。make-syscall.sh文件是shell脚本文件。该脚本文件读取syscalls.list文件内容,对syscalls.list文件中每一行数据进行解析。根据每一行数据生成一个.S文件。.S汇编文件封装了系统调用。syscall-template.S文件是系统调用封装的模板文件,包含了封装代码。每个生成的.S文件都将包含该文件的内容。
脚本封装
glibc支持不同的体系结构,不同的操作系统。本文只讨论i386机型下的linux操作系统。
i386机型linux操作系统下,make-syscall.sh文件在sysdeps/unix/make-syscall.sh。syscall-template.S文件在sysdeps/unix/syscall-template.S。syscalls.list文件则有多个,分别在sysdeps/unix/syscalls.list,sysdeps/unix/sysv/linux/syscalls.list,sysdeps/unix/sysv/linux/generic/syscalls.list,sysdeps/unix/sysv/linux/i386/syscalls.list。
make-syscall.sh文件首先读取syscalls.list文件中每一行内容。
syscalls.list文件的内容格式如下:

# File name Caller  Syscall name    Args    Strong name Weak names

accept      -   accept      Ci:iBN  __libc_accept   accept
access      -   access      i:si    __access    access
acct        -   acct        i:S acct
adjtime     -   adjtime     i:pp    __adjtime   adjtime
bind        -   bind        i:ipi   __bind      bind
chdir       -   chdir       i:s __chdir     chdir
......

syscalls.list文件由许多行组成,每一行都对应一个.S文件。每一行可分为6列。其中File name列指定生成.S文件的文件名。Caller列指定调用者。Syscall name列指定系统调用的名字。Args列指定系统调用的参数类型和个数以及返回值的类型。Strong name列指定系统调用对应函数的名字。Weak names列指定系统调用对应函数的名字的别称。可以使用别称来调用函数。
make-syscall.sh文件在解析完一行内容后将输出一个.S文件。以chdir为例,生成的.S文件的内容为:

#define SYSCALL_NAME chdir
#define SYSCALL_NARGS 1
#define SYSCALL_SYMBOL __chdir
#define SYSCALL_CANCELLABLE 0
#define SYSCALL_NOERRNO 0
#define SYSCALL_ERRVAL 0
#include <syscall-template.S>
weak_alias (__chdir, chdir)
hidden_weak (chdir)

SYSCALL_NAME宏定义系统调用的名字。可以从Syscall name列获取。
SYSCALL_NARGS宏定义系统调用的参数个数。可以通过解析Args列获取。
SYSCALL_SYMBOL宏定义系统调用的符号名称。可以从Strong name列获取。
SYSCALL_CANCELLABLE宏在生成的所有.S文件中它都定义为0。
SYSCALL_NOERRNO宏定义为1,则封装代码没有出错返回。用于getpid这些没有出错返回的系统调用。可以通过解析Args列设置。
SYSCALL_ERRVAL宏定义为1,则封装代码直接返回错误号,不是返回-1并将错误号放入errno中。生成的所有.S文件中它都定义为0。

weak_alias (__chdir, chdir)定义了__chdir函数的别称,我们可以调用chdir来调用__chdir。 chdir从Weak names列获取。

.S文件中引用了模板文件syscall-template.S。

syscall-template.S文件内容如下:

#if SYSCALL_CANCELLABLE
# include <sysdep-cancel.h>
#else
# include <sysdep.h>
#endif

#define syscall_hidden_def(SYMBOL)      hidden_def (SYMBOL)

#define T_PSEUDO(SYMBOL, NAME, N)       PSEUDO (SYMBOL, NAME, N)
#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N)   PSEUDO_NOERRNO (SYMBOL, NAME, N)
#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N)    PSEUDO_ERRVAL (SYMBOL, NAME, N)
#define T_PSEUDO_END(SYMBOL)            PSEUDO_END (SYMBOL)
#define T_PSEUDO_END_NOERRNO(SYMBOL)        
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值