Unix/Linux系统编程概念

以下内容引述<Unix/Linux系统编程手册>

系统调用

系统调用是受控的内核入口,进程可以请求内核以自己的名义去执行具体动作。

  • 系统调用将处理器从用户态切换为核心态,以便CPU访问受保护的内核内存;
  • 系统调用的组成是固定的,每个系统调用都是由一个唯一的数字来标志;
  • 每个系统调用可辅以一套参数,对用户空间(进程虚拟地址空间)与内核空间之间(相互)传递的信息加以规范

系统调用步骤

  1. 应用程序调用C语言函数库中的外壳函数,发起系统调用;
  2. 系统调用中断处理例程,外壳函数必须保证所有的系统调用参数可用。通过堆栈,这些参数传入外壳函数,但内核却希望将这些参数置于特定寄存器;
  3. 由于所有系统调用进入内核的方式相同,内核需要设法区分每个系统调用。为此,外壳函数会将系统调用编号复制到一个特殊的CPU寄存器(%eax)中;
  4. 外壳函数执行一条中断机器指令(int 0x80),引发处理器从用户态切换到内核态;并执行系统中断0x80的中断矢量所指向的代码;
  5. 为响应中断0x80,内核会调用system_call()例程来处理这次中断
  6. 如果系统调用服务例程的返回值表明调用有误,外壳函数会使用该值来设置全局变量errno,然后,外壳函数会返回到调用程序,并同时返回一个整形值,以表明系统调用是否成功。

GNU C语言函数库

标准C语言函数库的实现随Unix的实现而异,GNU C语言函数库是Linux上最常用的实现
确定某个与glibc动态链接的可执行文件,运行ldd(列出动态依赖性)程序,检查依赖列表

$ ldd myprog | grep libc
	libc.so.6 => /lib/tls/libc.so.6 (0x4004b000)

应用程序可以调用函数来确定系统的glibc版本

__GLIBC__
__GLIBC_MINOR__

如果glibc 2.12版本的系统上,两个值分别是2和12。
对于运行时版本,可以调用gnu_get_libc_version(),来确定运行时的glibc版本。

#include <gnu/libc-version.h>
const char* gnu_get_libc_version(void);
// returns pointers to null-terminated, staticaly allocated string containing GNU C library version number.

处理系统调用的错误

系统调用失败时,会给全局整形变量errno设置为一个正值,以标志具体的错误,程序应该包含**<errno.h>**头文件。
如果系统调用和库函数成功,errno值绝对不会被重置为0。
系统调用失败,使用函数perror()和strerror()打印

#include <stdio.h>
void perror(const char* msg);

#include <string.h>
char* strerror(int errnum);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值