Skip to content

其他

这里主要放一些零碎的内容。

系统调用

当你的程序调用open, read, write, close等函数时,就会触发系统调用(syscall)。系统调用本质是用户态进程与硬件设备交互的接口,内核负责检查系统调用的正确性,然后发出指令给硬件。作为应用程序开发者,不用关心底层硬件的实现细节,而只需要调用普通函数就可以使用系统调用了。glibc库进一步封装了细节,因此我们只需要使用glibc库暴露的API即可。

x86体系进入和退出系统调用有两种方式:

  • int $0x80 和 iret
  • sysenter 和 sysexit

第二种被称为快速系统调用。

无论哪种方式,最终结果都是跳转到系统调用处理函数(system call handler)。由于内核实现了很多不同的系统调用,因此进程必须传递一个名为系统调用号(system call number)的参数来识别所需的系统调用,这个参数存放在eax寄存器中。执行完系统调用后的返回值也放在eax寄存器中,其中正数或0表示系统调用成功,负数表示出错,存放于errno全局变量中。

系统调用处理流程是:

  • 将系统调用的参数写入CPU寄存器
  • 检查所有的系统调用参数
  • 将CPU中的参数拷贝至内核态堆栈
  • 调用名为系统调用服务例程(system call service routine)的C函数来处理系统调用
  • 退出系统调用处理程序,将内核栈中的值加载至寄存器,并从内核态切换回用户态

为了将系统调用号与对应的服务例程联系起来,内核定义了一个系统调用分派表(system call dispatch table),这个表存放在sys_call_table数组中。内核拿到系统调用号之后,就去sys_call_table中找到对应的系统调用实现函数去执行。执行完毕后,使用返回指令从内核态返回至用户态。

内核在执行系统调用的时候处于进程上下文。current指针指向当前任务,即引发系统调用的那个进程。在进程上下文中,内核可以休眠并且可以被抢占。因此必须保证系统调用时可重入的,因为新的进程可能会使用相同的系统调用。

终端快捷键

与终端打交道是每个Linux工程师绕不开的工作,下面介绍一些常用的快捷键,可以提升你输入命令的效率。

快捷键 功能描述
Ctrl + A 移动到行首
Ctrl + E 移动到行尾
Ctrl + U 删除光标至行首的所有内容
Ctrl + K 删除光标至行尾的所有内容
Ctrl + W 删除光标前的一个单词
Ctrl + L 清屏
Ctrl + D 注销或退出终端
Ctrl + Z 暂停进程
Ctrl + C 停止进程
Ctrl + R 逆向搜索历史命令
!! 重复执行最近的命令
!n 重复执行命令历史中的第 n 条命令
Ctrl + Shift + N 打开新的终端窗口
Ctrl + Shift + T 在当前终端中打开新的选项卡
Ctrl + Tab 或 Ctrl + PageDown 在终端的选项卡之间切换