====系统调用====
是应用程序和系统内核之间的API接口
是系统内核对外提供的一系列功能服务
系统调用的基本要点:
a.CPU从用户模式切换到内核模式
b.系统调用被优化了下,使用的是函数名称,而非调用数字号
c.系统调用可以从用户模式传递参数到内核模式,反之亦然
如果想要通过函数调用号使用系统调用,可以看看syscall函数的说明
系统调用看起来跟使用C函数差不多,使用函数名称来使用的系统调用
实际它的步骤比较多:
1.使用函数名的调用,实际是C语言库里面的wrapper函数
2.传递给wrapper函数的参数,都是通过栈的方式,wrapper函数再把栈上
参数拷贝到内核预定的寄存器中
3.因为所有的系统调用形式都是一样的,所以wrapper函数拷贝系统调用号
到eax寄存器中,标明使用的是哪个系统调用
4.wrapper函数执行trap(int 0x80)中断,使得CPU从用户模式切换到内核模式
执行中断向量表
5.内核使用system_call汇编子过程执行系统调用:
保存当前的寄存器内容
检查系统调用号
执行系统调用
恢复寄存器内容并将结果存放到栈上
返回到wrapper函数,从内核模式切换到用户模式
6.如果系统调用出错,会设置全局变量errno的值<表明错误原因>,并从
wrapper函数返回一个值表明调用出错
====库函数====
多种功能构成的C语言标准函数之一。大多数库函数不使用系统调用,一般都抽象在
系统调用之上,最常用的库版本是GNU C Library(glibc).
命令行执行/lib64/libc.so.6 或者/lib/libc.so.6可以打印版本相关的信息
====获取库版本信息====
#include <gnu/libc-version.h>
const char *gnu_get_libc_version(void);
返回一个以‘\0‘字符结尾的静态分配的字符串,类似2.12的字符串信息
同类型的函数有一个叫confstr
#include <unistd.h>
size_t confstr(int name, char *buf, size_t len);
使用方式类似confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
上述两个函数的结果打印类似下面的样本:
gnue_get_libc_version return: 2.12
confstr return: glibc 2.12
====处理错误====
#include <stdio.h>
void perror(const char *msg);
打印一个指向msg参数,后跟当前errno错误描述的字符串,输出到stderr流
#include <string.h>
char *strerror(int errnum);
返回一个静态分配的描述errnum错误信息的字符串,需要注意的是,该函数
返回指针指向的内容会被下一次该函数的调用覆盖,不适合多线程使用