其他¶
这里主要放一些零碎的内容。
系统调用¶
当你的程序调用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 | 在终端的选项卡之间切换 |