# 前言
之前弄个一段时间内核,而最近在应用程序特别是C++ 方面开发多一些。当前日常工作中碰到一些性能分析、不同锁API选择的问题,发现由于对用户态程序API背后的工作原理,特别是它和内核的调用关系、在内核中具体实现过程不甚清楚,导致前期的预期无法进行分析。为此,打算结合工作中碰到的问题,比如:
1. 用户态程序如何执行系统调用;
2. 用户态锁的底层实现及其和内核态锁的关系如何;
3. 用户态不同锁(自旋锁,读写锁,条件锁)和无锁机制的对比该如何做理论分析;
4.  Libaio 异步IO在内核中的具体使怎样实现的;
5.  系统调用、线程调度、中断分别对系统性能、CPU消耗的影响如何;
希望通过理清上面的这些基础问题,打通脑子中相互孤立的知识点,帮助他们建立起比较紧密的联系。
# 系统调用ABC
## 系统调用的功能
从操作系统的角度看,系统调用是内核提供用户态程序操作最底层软件或硬件的接口。Linux 系统中每种硬件系统架构都有自己的系统调用表,比如下面mips的系统调用表:
 “`
 EXPORT(sys_call_table)
    PTR sys_read            /* 5000 */
    PTR sys_write
    PTR sys_open
    PTR sys_close
….
PTR sys_statx
    PTR sys_rseq
    PTR sys_io_pgetevents
    .size   sys_call_table,.-sys_call_table
NESTED(handle_sys64, PT_SIZE, sp)
#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
    /*
     * When 32-bit compatibility is configured scall_o32.S
     * already did this.
     */
    .set    noat
    SAVE_SOME
    TRACE_IRQS_ON_RELOAD
    STI
    .set    at
…..
syscall_common:
    dsubu   t2, v0, __NR_64_Linux
    sltiu   t0, t2, __NR_64_Linux_syscalls + 1
    beqz    t0, illegal_syscall
    dsll    t0, t2, 3       # offset into table
    dla t2, sys_call_table
    daddu   t0, t2, t0
    ld  t2, (t0)        # syscall routine
    beqz    t2, illegal_syscall
    jalr    t2          # Do The Real Thing (TM)
 “`
# 系统调用的工作过程
## 从调用者的角度看:
(1)参考系统调用的操作规范,准备参数和数据;
(2)通过系统调用的标准接口模式,调用系统调用的接口;
## 从被调用者的角度看:
(1)将处理机状态由用户态转为系统态之后,由硬件和内核程序进行系统调用的一般性处理,即首先保护被中断进程的CPU环境;
(2)分析系统调用类型,转入相应的系统调用处理子程序;
(3)在系统调用处理子程序执行完后,恢复被中断的或设置新进程的CPU现场,然后返冋被中断进程或新进程,继续往下执行。
# 用户态程序快速调用系统调用
当前为了快速开发,也可以通过syscall 快速调用,比如下面Libaio的两个快速调用的实现:
“`
/* Actual syscalls */
int io_setup(int maxevents, io_context_t *ctxp) {
    return syscall(_io_setup, maxevents, ctxp);
}
int io_destroy(io_context_t ctx) {
    return syscall(__io_destroy, ctx);
}
“`
读者可以根据上面的示例,调用自己的系统调用。