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