打通用戶態程序和內核系列之一:用戶態程序如何執行系統調用

前言

以前弄個一段時間內核,而最近在應用程序特別是C++ 方面開發多一些。當前平常工做中碰到一些性能分析、不一樣鎖API選擇的問題,發現因爲對用戶態程序API背後的工做原理,特別是它和內核的調用關係、在內核中具體實現過程不甚清楚,致使前期的預期沒法進行分析。爲此,打算結合工做中碰到的問題,好比:架構

  1. 用戶態程序如何執行系統調用;
  2. 用戶態鎖的底層實現及其和內核態鎖的關係如何;
  3. 用戶態不一樣鎖(自旋鎖,讀寫鎖,條件鎖)和無鎖機制的對比該如何作理論分析;
  4.  Libaio 異步IO在內核中的具體使怎樣實現的;
  5.  系統調用、線程調度、中斷分別對系統性能、CPU消耗的影響如何;

但願經過理清上面的這些基礎問題,打通腦子中相互孤立的知識點,幫助他們創建起比較緊密的聯繫。異步

系統調用ABC

系統調用的功能

從操做系統的角度看,系統調用是內核提供用戶態程序操做最底層軟件或硬件的接口。Linux 系統中每種硬件系統架構都有本身的系統調用表,好比下面mips的系統調用表:ide

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環境;this

(2)分析系統調用類型,轉入相應的系統調用處理子程序;操作系統

(3)在系統調用處理子程序執行完後,恢復被中斷的或設置新進程的CPU現場,而後返冋被中斷進程或新進程,繼續往下執行。線程

用戶態程序快速調用系統調用

當前爲了快速開發,也能夠經過syscall 快速調用,好比下面Libaio的兩個快速調用的實現:code

/* 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);
}

讀者能夠根據上面的示例,調用本身的系統調用。接口

相關文章
相關標籤/搜索