偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

為什么 Linux 系統(tǒng)調(diào)用會(huì)消耗較多資源

系統(tǒng) Linux
當(dāng)我們?cè)诰帉憫?yīng)用程序時(shí),系統(tǒng)調(diào)用并不是一個(gè)離我們很遠(yuǎn)的概念,一個(gè)簡(jiǎn)單的 Hello World 會(huì)在執(zhí)行時(shí)觸發(fā)幾十次系統(tǒng)調(diào)用,而在線上出現(xiàn)性能問題時(shí),可能也需要我們與系統(tǒng)調(diào)用打交道。

系統(tǒng)調(diào)用是計(jì)算機(jī)程序在執(zhí)行的過程中向操作系統(tǒng)內(nèi)核申請(qǐng)服務(wù)的方法,這可能包含硬件相關(guān)的服務(wù)、新進(jìn)程的創(chuàng)建和執(zhí)行以及進(jìn)程調(diào)度,對(duì)操作系統(tǒng)稍微有一些了解的人都知道 — 系統(tǒng)調(diào)用為用戶程序提供了操作系統(tǒng)的接口。

圖 1 - 操作系統(tǒng)接口

C 語(yǔ)言的著名的 glibc 封裝了操作系統(tǒng)提供的系統(tǒng)調(diào)用并提供了定義良好的接口[^2],工程師可以直接使用器中封裝好的函數(shù)開發(fā)上層的應(yīng)用程序,其他編程語(yǔ)言的標(biāo)準(zhǔn)庫(kù)也會(huì)封裝系統(tǒng)調(diào)用,它們對(duì)外提供語(yǔ)言原生的接口,內(nèi)部使用匯編語(yǔ)言觸發(fā)系統(tǒng)調(diào)用。

我們?cè)谑褂脴?biāo)準(zhǔn)庫(kù)時(shí)需要經(jīng)常與系統(tǒng)調(diào)用打交道,只是很多時(shí)候我們不知道標(biāo)準(zhǔn)庫(kù)背后的實(shí)現(xiàn),以常見的 Hello World 程序?yàn)槔?,這么簡(jiǎn)單的幾行函數(shù)在真正運(yùn)行時(shí)會(huì)執(zhí)行幾十次系統(tǒng)調(diào)用:

  1. #include <stdio.h> 
  2. int main() { 
  3.    printf("Hello, World!"); 
  4.    return 0; 
  5.  
  6. $ gcc hello.c -o hello 
  7. $ strace ./hello 
  8. execve("./hello", ["./hello"], 0x7ffd64dd8090 /* 23 vars */) = 0 
  9. brk(NULL)                               = 0x557b449db000 
  10. access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory) 
  11. access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory) 
  12. openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 
  13. fstat(3, {st_mode=S_IFREG|0644, st_size=26133, ...}) = 0 
  14. mmap(NULL, 26133, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f645455a000 
  15. close(3)                                = 0 
  16. ... 
  17. munmap(0x7f645455a000, 26133)           = 0 
  18. fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0 
  19. brk(NULL)                               = 0x557b449db000 
  20. brk(0x557b449fc000)                     = 0x557b449fc000 
  21. write(1, "Hello, World!", 13Hello, World!)           = 13 
  22. exit_group(0)                           = ? 
  23. +++ exited with 0 +++ 

strace 是 Linux 中用于監(jiān)控和篡改進(jìn)程與內(nèi)核之間操作的工具,上述命令會(huì)打印出 hello 執(zhí)行過程中觸發(fā)系統(tǒng)調(diào)用、參數(shù)以及返回值等信息。執(zhí)行 Hello World 程序時(shí)觸發(fā)的多數(shù)系統(tǒng)調(diào)用都是程序啟動(dòng)觸發(fā)的,只有 munmap 后的系統(tǒng)調(diào)用才是 printf函數(shù)觸發(fā)的,作為應(yīng)用程序我們能做的事情非常有限,很多功能都需要依賴操作系統(tǒng)提供的服務(wù)。

多數(shù)編程語(yǔ)言的函數(shù)調(diào)用只需要分配新的棧空間、向寄存器寫入?yún)?shù)并執(zhí)行 CALL 匯編指令跳轉(zhuǎn)到目標(biāo)地址執(zhí)行函數(shù),在函數(shù)返回時(shí)通過棧或者寄存器返回參數(shù)。與函數(shù)調(diào)用相比,系統(tǒng)調(diào)用會(huì)消耗更多的資源,如下圖所示,使用 SYSCALL 指定執(zhí)行系統(tǒng)調(diào)用消耗的時(shí)間是 C 函數(shù)調(diào)用的幾十倍:

圖 2 - 系統(tǒng)調(diào)用與函數(shù)調(diào)用耗時(shí)比較

上圖中的 vDSO 全稱是虛擬動(dòng)態(tài)鏈接對(duì)象(Virtual Dynamically Shared Object、vDSO),它可以減少系統(tǒng)調(diào)用的消耗的時(shí)間,我們會(huì)在后面詳細(xì)分析它的實(shí)現(xiàn)原理。

getpid(2) 是一個(gè)相對(duì)比較快的系統(tǒng)調(diào)用,該系統(tǒng)調(diào)用不包含任何參數(shù),只會(huì)切換到內(nèi)核態(tài)、讀取變量并返回 PID,我們可以將它的執(zhí)行時(shí)間當(dāng)做系統(tǒng)調(diào)用的基準(zhǔn)測(cè)試;除了 getpid(2) 之外,使用 close(999) 系統(tǒng)調(diào)用關(guān)閉不存在的文件描述符會(huì)消耗更少的資源[^5],與 getpid(2) 相比大概會(huì)少 20 個(gè) CPU 周期[^6],當(dāng)然想要實(shí)現(xiàn)用于測(cè)試額外開銷的系統(tǒng)調(diào)用,使用自定義的空函數(shù)應(yīng)該是最完美的選擇,感興趣的讀者可以自行嘗試一下。

圖 3 - 系統(tǒng)調(diào)用的三種方法

從上面的系統(tǒng)調(diào)用與函數(shù)調(diào)用的基準(zhǔn)測(cè)試中,我們可以發(fā)現(xiàn)不使用 vSDO 加速的系統(tǒng)調(diào)用需要的時(shí)間是普通函數(shù)調(diào)用的幾十倍,為什么系統(tǒng)調(diào)用會(huì)帶來(lái)這么大的額外開銷,它在內(nèi)部到底執(zhí)行了哪些工作呢,本文將介紹 Linux 執(zhí)行系統(tǒng)調(diào)用的三種方法:

  • 使用軟件中斷(Software interrupt)觸發(fā)系統(tǒng)調(diào)用;
  • 使用 SYSCALL / SYSENTER 等匯編指令觸發(fā)系統(tǒng)調(diào)用;
  • 使用虛擬動(dòng)態(tài)共享對(duì)象(virtual dynamic shared object、vDSO)執(zhí)行系統(tǒng)調(diào)用;

軟件中斷

中斷是向處理器發(fā)送的輸入信號(hào),它能夠表示某個(gè)時(shí)間需要操作系統(tǒng)立刻處理,如果操作系統(tǒng)接收了中斷,那么處理器會(huì)暫停當(dāng)前的任務(wù)、存儲(chǔ)上下文狀態(tài)、并執(zhí)行中斷處理器處理發(fā)生的事件,在中斷處理器結(jié)束后,當(dāng)前處理器會(huì)恢復(fù)上下文繼續(xù)完成之前的工作。

圖 4 - 硬件中斷和軟件中斷

根據(jù)事件發(fā)出者的不同,我們可以將中斷分成硬件和軟件中斷兩種,硬件中斷是由處理器外部的設(shè)備觸發(fā)的電子信號(hào);而軟件中斷是由處理器在執(zhí)行特定指令時(shí)觸發(fā)的,某些特殊的指令也可以故意觸發(fā)軟件中斷]。

在 32 位的 x86 的系統(tǒng)上,我們可以使用 INT 指令來(lái)觸發(fā)軟件中斷,早期的 Linux 會(huì)使用 INT 0x80 觸發(fā)軟件中斷、注冊(cè)特定的中斷處理器 entry_INT80_32 來(lái)處理系統(tǒng)調(diào)用,我們來(lái)了解一下使用軟件中斷執(zhí)行系統(tǒng)調(diào)用的具體過程:

(1) 應(yīng)用程序通過調(diào)用 C 語(yǔ)言庫(kù)中的函數(shù)發(fā)起系統(tǒng)調(diào)用;

(2) C 語(yǔ)言函數(shù)通過棧收到調(diào)用方傳入的參數(shù)并將系統(tǒng)調(diào)用需要的參數(shù)拷貝到寄存器;

(3) Linux 中的每一個(gè)系統(tǒng)調(diào)用都有特定的序號(hào),函數(shù)會(huì)將系統(tǒng)調(diào)用的編號(hào)拷貝到 eax寄存器;

(4) 函數(shù)執(zhí)行 INT 0x80 指令,處理器會(huì)從用戶態(tài)切換到內(nèi)核態(tài)并執(zhí)行預(yù)先定義好的處理器;

(5) 執(zhí)行中斷處理器 entry_INT80_32 處理系統(tǒng)調(diào)用;

  • 執(zhí)行 SAVE_ALL 將寄存器的值存儲(chǔ)到內(nèi)核棧上并調(diào)用 do_int80_syscall_32;
  • 調(diào)用 do_syscall_32_irqs_on 檢查系統(tǒng)調(diào)用的序號(hào)是否合法;
  • 在系統(tǒng)調(diào)用表 ia32_sys_call_table 中查找對(duì)應(yīng)的系統(tǒng)調(diào)用實(shí)現(xiàn)并傳入寄存器的值;
  • 系統(tǒng)調(diào)用在執(zhí)行期間會(huì)檢查參數(shù)的合法性、在用戶態(tài)內(nèi)存和內(nèi)核態(tài)內(nèi)存之間傳輸數(shù)據(jù),系統(tǒng)調(diào)用的結(jié)果會(huì)被存儲(chǔ)到 eax 寄存器中;
  • 從內(nèi)核棧中恢復(fù)寄存器的值并將返回值放到棧上;
  • 系統(tǒng)調(diào)用會(huì)返回 C 函數(shù),包裝函數(shù)會(huì)將結(jié)果返回給應(yīng)用程序;

(6) 如果系統(tǒng)調(diào)用服務(wù)在執(zhí)行過程中出現(xiàn)了錯(cuò)誤,C 語(yǔ)言函數(shù)會(huì)將錯(cuò)誤存儲(chǔ)在全局變量 errno 中并根據(jù)系統(tǒng)調(diào)用的結(jié)果返回一個(gè)用整數(shù) int 表示的狀態(tài);

圖 5 - 系統(tǒng)調(diào)用的執(zhí)行步驟

從上述系統(tǒng)調(diào)用的執(zhí)行過程中,我們可以看到基于軟件中斷的系統(tǒng)調(diào)用是一個(gè)比較復(fù)雜的流程,應(yīng)用程序通過軟件中斷陷入內(nèi)核態(tài)并在內(nèi)核態(tài)查詢并執(zhí)行系統(tǒng)調(diào)用表注冊(cè)的函數(shù),整個(gè)過程不僅需要存儲(chǔ)寄存器中的數(shù)據(jù)、從用戶態(tài)切換至內(nèi)核態(tài),還需要完成驗(yàn)證參數(shù)的合法性,與函數(shù)調(diào)用的過程相比確實(shí)會(huì)帶來(lái)很多的額外開銷。

實(shí)際上,使用 INT 0x80 來(lái)觸發(fā)系統(tǒng)調(diào)用早就是過去時(shí)了,大多數(shù)的程序都會(huì)盡量避免這種觸發(fā)方式。然而這一規(guī)則也不是通用的,因?yàn)?Go 語(yǔ)言團(tuán)隊(duì)在做基準(zhǔn)測(cè)試時(shí)發(fā)現(xiàn) INT 0x80 觸發(fā)系統(tǒng)調(diào)用在部分操作系統(tǒng)上與其他方式有著幾乎相同的性能,所以在 Android/386 和 Linux/386 等架構(gòu)上仍然會(huì)使用中斷來(lái)執(zhí)行系統(tǒng)調(diào)用。

匯編指令

因?yàn)槭褂密浖袛鄬?shí)現(xiàn)的系統(tǒng)調(diào)用在 Pentium 4 的處理器上表現(xiàn)非常差。Linux 為了解決這個(gè)問題,在較新的版本使用了新的匯編指令 SYSENTER / SYSCALL,它們是 Intel 和 AMD 上用于實(shí)現(xiàn)快速系統(tǒng)調(diào)用的指令,我們會(huì)在 32 位的操作系統(tǒng)上使用 SYSENTER / SYSEXIT,在 64 位的操作系統(tǒng)上使用 SYSCALL / SYSRET:

圖 6 - 快速系統(tǒng)調(diào)用指令

上述的幾個(gè)匯編指令是低延遲的系統(tǒng)調(diào)用和返回指令,它們會(huì)認(rèn)為操作系統(tǒng)實(shí)現(xiàn)了線性內(nèi)存模型(Linear-memory Model),極大地簡(jiǎn)化了操作系統(tǒng)系統(tǒng)調(diào)用和返回的過程,其中包括不必要的檢查、預(yù)加載參數(shù)等,與軟件中斷驅(qū)動(dòng)的系統(tǒng)調(diào)用相比,使用快速系統(tǒng)調(diào)用指令可以減少 25% 的時(shí)鐘周期。

線性內(nèi)存模型是一種內(nèi)存尋址的常見范式,在這種模式中,線性內(nèi)存與應(yīng)用程序存儲(chǔ)在單一連續(xù)的空間地址中,CPU 可以不借助內(nèi)存碎片或者分頁(yè)技術(shù)使用地址直接訪問可用的內(nèi)存地址。

在 64 位的操作系統(tǒng)上,我們會(huì)使用 SYSCALL / SYSRET 進(jìn)入和退出系統(tǒng)調(diào)用,該指令會(huì)在操作系統(tǒng)最高權(quán)限等級(jí)中執(zhí)行。內(nèi)核在初始化時(shí)會(huì)調(diào)用 syscall_init 函數(shù)將 entry_SYSCALL_64 存入 MSR 寄存器(Model Specific Register、MSR)中,MSR 寄存器是 x86 指令集中用于調(diào)試、追蹤以及性能監(jiān)控的控制寄存器:

  1. void syscall_init(void) { 
  2.     wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS); 
  3.     wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64); 
  4.     ... 

當(dāng)內(nèi)核收到了用戶程序觸發(fā)的系統(tǒng)調(diào)用時(shí),它會(huì)在 MSR 寄存器中讀取需要執(zhí)行的函數(shù)并按照 x86-64 的調(diào)用慣例在寄存器中讀取系統(tǒng)調(diào)用的編號(hào)以及參數(shù),你能在 entry_SYSCALL_64 函數(shù)的注釋中找到相關(guān)的調(diào)用慣例。

匯編函數(shù) entry_SYSCALL_64 會(huì)在執(zhí)行的過程中調(diào)用 do_syscall_64,它的實(shí)現(xiàn)與上一節(jié)中的 do_int80_syscall_32 有些相似,它們都會(huì)在系統(tǒng)調(diào)用表中查找函數(shù)并傳入寄存器中的參數(shù)。

與 INT 0x80 通過觸發(fā)軟件中斷實(shí)現(xiàn)系統(tǒng)調(diào)用不同,SYSENTER 和 SYSCALL 是專門為系統(tǒng)調(diào)用設(shè)計(jì)的匯編指令,它們不需要在中斷描述表(Interrupt Descriptor Table、IDT)中查找系統(tǒng)調(diào)用對(duì)應(yīng)的執(zhí)行過程,也不需要保存堆棧和返回地址等信息,所以能夠減少所需要的額外開銷。

vDSO

虛擬動(dòng)態(tài)共享對(duì)象(virtual dynamic shared object、vDSO)是 Linux 內(nèi)核對(duì)用戶空間暴露內(nèi)核空間部分函數(shù)的一種機(jī)制,簡(jiǎn)單來(lái)說(shuō),我們將 Linux 內(nèi)核中不涉及安全的系統(tǒng)調(diào)用直接映射到用戶空間,這樣用戶空間中的應(yīng)用程序在調(diào)用這些函數(shù)時(shí)就不需要切換到內(nèi)核態(tài)以減少性能上的損失。

vDSO 使用了標(biāo)準(zhǔn)的鏈接和加載技術(shù),作為一個(gè)動(dòng)態(tài)鏈接庫(kù),它由 Linux 內(nèi)核提供并映射到每一個(gè)正在執(zhí)行的進(jìn)程中,我們可以使用如下所示的命令查看該動(dòng)態(tài)鏈接庫(kù)在進(jìn)程中的位置:

  1. $ ldd /bin/cat 
  2.     linux-vdso.so.1 (0x00007fff2709c000) 
  3.     ... 
  4.  
  5. $ cat /proc/self/maps 
  6. ... 
  7. 7f28953ce000-7f28953cf000 r--p 00027000 fc:01 2079                       /lib/x86_64-linux-gnu/ld-2.27.so 
  8. 7f28953cf000-7f28953d0000 rw-p 00028000 fc:01 2079                       /lib/x86_64-linux-gnu/ld-2.27.so 
  9. 7f28953d0000-7f28953d1000 rw-p 00000000 00:00 0 
  10. 7ffe8ca4d000-7ffe8ca6e000 rw-p 00000000 00:00 0                          [stack] 
  11. 7ffe8ca8d000-7ffe8ca90000 r--p 00000000 00:00 0                          [vvar] 
  12. 7ffe8ca90000-7ffe8ca92000 r-xp 00000000 00:00 0                          [vdso] 
  13. ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0   

因?yàn)?vDSO 是由操作系統(tǒng)直接提供的,所以它并不存在對(duì)應(yīng)的文件,在程序執(zhí)行的過程中我們也能在虛擬內(nèi)存中看到它加載的位置。vDSO 可以為用戶程序提供虛擬的系統(tǒng)調(diào)用,它會(huì)使用內(nèi)核提供的數(shù)據(jù)在用戶態(tài)模擬系統(tǒng)調(diào)用:

圖 7 - 內(nèi)核和用戶控件的初始化

系統(tǒng)調(diào)用 gettimeofday 是一個(gè)非常好的例子,如上圖所示,使用 vDSO 的系統(tǒng)調(diào)用 gettimeofday 會(huì)按照如下所示的步驟進(jìn)行初始化:

  • 內(nèi)核中的 ELF 加載器會(huì)負(fù)責(zé)映射 vDSO 的內(nèi)存頁(yè)并設(shè)置輔助向量(Auxiliary Vector)中 AT_SYSINFO_EHDR,該標(biāo)簽存儲(chǔ)了 vDSO 的基地址;
  • 動(dòng)態(tài)鏈接器會(huì)查詢輔助向量中 AT_SYSINFO_EHDR,如果設(shè)置了該標(biāo)簽會(huì)鏈接 vDSO;
  • libc 在初始化時(shí)會(huì)在 vDSO 中查找 __vdso_gettimeofday 符號(hào)并將符號(hào)鏈接到全局的函數(shù)指針上;

除了 gettimeofday 之外,多數(shù)架構(gòu)上的 vDSO 還包含 clock_gettime、clock_getres 和 rt_sigreturn 等三個(gè)系統(tǒng)調(diào)用,這些系統(tǒng)調(diào)用完成功能相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,也不會(huì)帶來(lái)安全上的問題,所以將它們映射到用戶空間可以明顯地提高系統(tǒng)調(diào)用的性能,就像我們?cè)趫D二中看到的,使用 vDSO 可以將上述幾個(gè)系統(tǒng)調(diào)用的時(shí)間提高幾十倍。

總結(jié)

當(dāng)我們?cè)诰帉憫?yīng)用程序時(shí),系統(tǒng)調(diào)用并不是一個(gè)離我們很遠(yuǎn)的概念,一個(gè)簡(jiǎn)單的 Hello World 會(huì)在執(zhí)行時(shí)觸發(fā)幾十次系統(tǒng)調(diào)用,而在線上出現(xiàn)性能問題時(shí),可能也需要我們與系統(tǒng)調(diào)用打交道。雖然程序中的系統(tǒng)調(diào)用非常頻繁,但是與普通的函數(shù)調(diào)用相比,它會(huì)帶來(lái)明顯地額外開銷:

  • 使用軟件中斷觸發(fā)的系統(tǒng)調(diào)用需要保存堆棧和返回地址等信息,還要在中斷描述表中查找系統(tǒng)調(diào)用的響應(yīng)函數(shù),雖然多數(shù)的操作系統(tǒng)不會(huì)使用 INT 0x80 觸發(fā)系統(tǒng)調(diào)用,但是在一些特殊場(chǎng)景下,我們?nèi)匀恍枰眠@一古老的技術(shù);
  • 使用匯編指令 SYSCALL / SYSENTER 執(zhí)行系統(tǒng)調(diào)用是今天最常見的方法,作為專門為系統(tǒng)調(diào)用打造的指令,它們可以省去一些不必要的步驟,降低系統(tǒng)調(diào)用的開銷;
  • 使用 vSDO 執(zhí)行系統(tǒng)調(diào)用是操作系統(tǒng)為我們提供的最快路徑,該方式可以將系統(tǒng)調(diào)用的開銷與函數(shù)調(diào)用拉平,不過因?yàn)閷?nèi)核態(tài)的系統(tǒng)調(diào)用映射到『用戶態(tài)』確實(shí)存在安全風(fēng)險(xiǎn),所以操作系統(tǒng)也僅會(huì)放開有限的系統(tǒng)調(diào)用;

應(yīng)用程序能夠完成的工作相當(dāng)有限,我們需要使用操作系統(tǒng)提供的服務(wù)才能編寫功能豐富的用戶程序。系統(tǒng)調(diào)用作為操作系統(tǒng)提供的接口,它與底層的硬件關(guān)系十分緊密,因?yàn)橛布姆N類繁雜,所以不同架構(gòu)要使用不同的指令,隨著內(nèi)核的快速演進(jìn),想要找到準(zhǔn)確的資料也非常困難,不過了解不同系統(tǒng)調(diào)用的實(shí)現(xiàn)原理對(duì)我們認(rèn)識(shí)操作系統(tǒng)也有很大的幫助。到最后,我們還是來(lái)看一些比較開放的相關(guān)問題,有興趣的讀者可以仔細(xì)思考一下下面的問題:

  • vDSO 提供的系統(tǒng)調(diào)用 rt_sigreturn 有哪些作用?
  • vDSO 提供的四種系統(tǒng)調(diào)用中三種都與獲取時(shí)間有關(guān),為什么它可以在用戶態(tài)提供 rt_sigreturn,不存在安全風(fēng)險(xiǎn)么?

 

責(zé)任編輯:趙寧寧 來(lái)源: 真沒什么邏輯
相關(guān)推薦

2022-04-06 07:51:21

數(shù)據(jù)庫(kù)Web連接池

2012-05-02 10:08:51

桌面Linux微軟

2017-01-05 18:43:58

閏秒Linux服務(wù)器

2016-11-08 11:06:20

2022-03-07 11:25:29

移動(dòng)網(wǎng)絡(luò)5G綠色收益

2021-01-25 07:14:53

Cloud DevOps云計(jì)算

2022-04-13 20:53:15

Spring事務(wù)管理

2023-03-22 09:10:18

IT文檔語(yǔ)言

2014-03-05 14:58:00

蘋果CarPlayiOS

2015-12-07 10:49:43

卸載App用戶體驗(yàn)

2022-05-11 08:22:54

IO負(fù)載NFSOS

2012-03-26 10:26:43

openstackeucalyptus

2012-08-17 10:01:07

云計(jì)算

2021-07-09 09:24:06

NanoID UUID軟件開發(fā)

2020-03-30 15:05:46

Kafka消息數(shù)據(jù)

2020-05-21 11:23:08

微軟LinuxWindows

2018-05-14 11:07:48

服務(wù)器Linux系統(tǒng)

2010-01-06 15:41:07

Linux操作系統(tǒng)

2024-02-21 21:28:29

Linux系統(tǒng)

2010-01-05 17:16:51

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)