欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    首先說說系統(tǒng)調(diào)用是什么,當(dāng)你的代碼需要做IO操作(open、read、write)、或者是進(jìn)行內(nèi)存操作(mmpa、sbrk)、甚至是說要獲取一個(gè)系統(tǒng)時(shí)間(),就需要通過系統(tǒng)調(diào)用來和內(nèi)核進(jìn)行交互。無論你的用戶程序是用什么語言實(shí)現(xiàn)的,是php、c、java還是go,只要你是建立在Linux內(nèi)核之上的,你就繞不開系統(tǒng)調(diào)用。

    圖1 系統(tǒng)調(diào)用在計(jì)算機(jī)系統(tǒng)中的位置

    大家可以通過命令來查看到你的程序正在執(zhí)行哪些系統(tǒng)調(diào)用。比如我查看了一個(gè)正在生產(chǎn)環(huán)境上運(yùn)行的nginx當(dāng)前所執(zhí)行的系統(tǒng)調(diào)用,如下:

    # strace -p 28927
    Process 28927 attached  
    epoll_wait(6, {{EPOLLIN, {u32=96829456, u64=140312383422480}}}, 512, -1) = 1  
    accept4(8, {sa_family=AF_INET, sin_port=htons(55465), sin_addr=inet_addr("10.143.52.149")}, [16], SOCK_NONBLOCK) = 13  
    epoll_ctl(6, EPOLL_CTL_ADD, 13, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u32=96841984, u64=140312383435008}}) = 0  
    epoll_wait(6, {{EPOLLIN, {u32=96841984, u64=140312383435008}}}, 512, 60000) = 1  

    簡單介紹了下系統(tǒng)調(diào)用,那么相信各位同學(xué)都聽說過一個(gè)建議,就是系統(tǒng)調(diào)用的開銷很大,要盡量減少系統(tǒng)調(diào)用的次數(shù),以提高你的代碼的性能。那么問題來了,我們是否可以給出量化的指標(biāo)。一次系統(tǒng)調(diào)用到底要多大的開銷,需要消耗掉多少CPU時(shí)間?好了,廢話不多說,我們直接進(jìn)行一些測(cè)試,用數(shù)據(jù)來說話。

    使用命令進(jìn)行實(shí)驗(yàn)

    首先我對(duì)線上正在服務(wù)的nginx進(jìn)行統(tǒng)計(jì),可以看出系統(tǒng)調(diào)用的耗時(shí)大約分布在1-15us左右。因此我們可以大致得出結(jié)論,系統(tǒng)調(diào)用的耗時(shí)大約是1us級(jí)別的,當(dāng)然由于不同系統(tǒng)調(diào)用執(zhí)行的操作不一樣,執(zhí)行當(dāng)時(shí)的環(huán)境不一樣,因此不同的時(shí)刻,不同的調(diào)用之間會(huì)存在耗時(shí)上的上下波動(dòng)。

    # strace -cp 8527  
    strace: Process 8527 attached  
    % time     seconds  usecs/call     calls    errors syscall  
    ------ ----------- ----------- --------- --------- ----------------  
     44.44    0.000727          12        63           epoll_wait  
     27.63    0.000452          13        34           sendto 
    

    360系統(tǒng)急救箱進(jìn)程模式_有哪些是系統(tǒng)進(jìn)程調(diào)用_word進(jìn)程啟動(dòng)失敗是否重新調(diào)用

    10.39 0.000170 7 25 21 accept4 5.68 0.000093 8 12 write 5.20 0.000085 2 38 recvfrom 4.10 0.000067 17 4 writev 2.26 0.000037 9 4 close 0.31 0.000005 1 4 epoll_ctl

    使用time命令進(jìn)行實(shí)驗(yàn)

    我們?cè)偈止懚未a,對(duì)read系統(tǒng)調(diào)用進(jìn)行測(cè)試,代碼如下

    #include   
    #include  
    #include  
    int main()  
    {  	
    	char    c;  
    	int     in;
    	int 	i;
    	in = open("in.txt", O_RDONLY);  
    

    360系統(tǒng)急救箱進(jìn)程模式_word進(jìn)程啟動(dòng)失敗是否重新調(diào)用_有哪些是系統(tǒng)進(jìn)程調(diào)用

    for(i=0; i<1000000; i++){ read(in,&c,1); } return 0; }

    注意,只能用read庫函數(shù)來進(jìn)行測(cè)試,不要使用fread。因此fread是庫函數(shù)在用戶態(tài)保留了緩存的,而read是你每調(diào)用一次,內(nèi)核就老老實(shí)實(shí)幫你執(zhí)行一次read系統(tǒng)調(diào)用。

    首先創(chuàng)建一個(gè)固定大小為1M的文件

    dd if=/dev/zero of=in.txt bs=1M count=1

    然后再編譯代碼進(jìn)行測(cè)試

    #gcc main.c -o main  
    #time ./main  
    real    0m0.258s   
    user    0m0.030s  
    sys     0m0.227s  

    由于上述實(shí)驗(yàn)是循環(huán)了100萬次,所以平均每次系統(tǒng)調(diào)用耗時(shí)大約是200ns多一些。

    Perf命令查看系統(tǒng)調(diào)用消耗的CPU指令數(shù)

    x86-64 CPU有一個(gè)特權(quán)級(jí)別的概念。內(nèi)核運(yùn)行在最高級(jí)別,稱為Ring0,用戶程序運(yùn)行在Ring3。正常情況下,用戶進(jìn)程都是運(yùn)行在Ring3級(jí)別的,但是磁盤、網(wǎng)卡等外設(shè)只能在內(nèi)核Ring0級(jí)別下來來訪問。因此當(dāng)我們用戶態(tài)程序需要訪問磁盤等外設(shè)的時(shí)候,要通過系統(tǒng)調(diào)用進(jìn)行這種特權(quán)級(jí)別的切換

    對(duì)于普通的函數(shù)調(diào)用來說,一般只需要進(jìn)行幾次寄存器操作,如果有參數(shù)或返回函數(shù)的話,再進(jìn)行幾次用戶棧操作而已。而且用戶棧早已經(jīng)被CPU cache接住,也并不需要真正進(jìn)行內(nèi)存IO。

    但是對(duì)于系統(tǒng)調(diào)用來說,這個(gè)過程就要麻煩一些了。系統(tǒng)調(diào)用時(shí)需要從用戶態(tài)切換到內(nèi)核態(tài)。由于內(nèi)核態(tài)的棧用的是內(nèi)核棧,因此還需要進(jìn)行棧的切換。SS、ESP、、CS和EIP寄存器全部都需要進(jìn)行切換。

    有哪些是系統(tǒng)進(jìn)程調(diào)用_360系統(tǒng)急救箱進(jìn)程模式_word進(jìn)程啟動(dòng)失敗是否重新調(diào)用

    而且棧切換后還可能有一個(gè)隱性的問題,那就是CPU調(diào)度的指令和數(shù)據(jù)一定程度上破壞了局部性原來,導(dǎo)致一二三級(jí)數(shù)據(jù)緩存、TLB頁表緩存的命中率一定程度上有所下降。

    除了上述堆棧和寄存器等環(huán)境的切換外,系統(tǒng)調(diào)用由于特權(quán)級(jí)別比較高,也還需要進(jìn)行一系列的權(quán)限校驗(yàn)、有效性等檢查相關(guān)操作。所以系統(tǒng)調(diào)用的開銷相對(duì)函數(shù)調(diào)用來說要大的多。我們?cè)诘幕A(chǔ)上計(jì)算一下每個(gè)系統(tǒng)調(diào)用需要執(zhí)行的CPU指令數(shù)。

    # perf stat ./main
     Performance counter stats for './main':
            251.508810 task-clock                #    0.997 CPUs utilized
                     1 context-switches          #    0.000 M/sec
                     1 CPU-migrations            #    0.000 M/sec
                    97 page-faults               #    0.000 M/sec
           600,644,444 cycles                    #    2.388 GHz                     [83.38%]
           122,000,095 stalled-cycles-frontend   #   20.31% frontend cycles idle    [83.33%]
            45,707,976 stalled-cycles-backend    #    7.61% backend  cycles idle    [66.66%]
         1,008,492,870 instructions              #    1.68  insns per cycle
                                                 #    0.12  stalled cycles per insn [83.33%]
           177,244,889 branches                  #  704.726 M/sec                   [83.32%]
                 7,583 branch-misses             #    0.00% of all branches         [83.33%]
    

    對(duì)實(shí)驗(yàn)代碼進(jìn)行稍許改動(dòng),把for循環(huán)中的read調(diào)用注釋掉,再重新編譯運(yùn)行

    有哪些是系統(tǒng)進(jìn)程調(diào)用_360系統(tǒng)急救箱進(jìn)程模式_word進(jìn)程啟動(dòng)失敗是否重新調(diào)用

    # gcc main.c -o main  
    # perf stat ./main  
     Performance counter stats for './main':  
              3.196978 task-clock                #    0.893 CPUs utilized
                     0 context-switches          #    0.000 M/sec
                     0 CPU-migrations            #    0.000 M/sec
                    98 page-faults               #    0.031 M/sec
             7,616,703 cycles                    #    2.382 GHz                       [68.92%]
             5,397,528 stalled-cycles-frontend   #   70.86% frontend cycles idle      [68.85%]  
             1,574,438 stalled-cycles-backend    #   20.67% backend  cycles idle  
             3,359,090 instructions              #    0.44  insns per cycle  
                                                 #    1.61  stalled cycles per insn  
             1,066,900 branches                  #  333.721 M/sec
                   799 branch-misses             #    0.07% of all branches           [80.14%]  
           0.003578966 seconds time elapsed  
    

    有哪些是系統(tǒng)進(jìn)程調(diào)用_360系統(tǒng)急救箱進(jìn)程模式_word進(jìn)程啟動(dòng)失敗是否重新調(diào)用

    平均每次系統(tǒng)調(diào)用CPU需要執(zhí)行的指令數(shù)(1,008,492,870 - 3,359,090)/ = 1005。

    深挖系統(tǒng)調(diào)用的實(shí)現(xiàn)

    如果非要扒到內(nèi)核的實(shí)現(xiàn)上,我建議大家參考一下《深入理解LINUX內(nèi)核-第十章系統(tǒng)調(diào)用》。最初系統(tǒng)調(diào)用是通過匯編指令int(中斷)來實(shí)現(xiàn)的,當(dāng)用戶態(tài)進(jìn)程發(fā)出int $0x80指令時(shí)有哪些是系統(tǒng)進(jìn)程調(diào)用,CPU切換到內(nèi)核態(tài)并開始執(zhí)行函數(shù)。 只不過后來大家覺得系統(tǒng)調(diào)用實(shí)在是太慢了,因?yàn)閕nt指令要執(zhí)行一致性和安全性檢查。后來Intel又提供了“快速系統(tǒng)調(diào)用”的指令,我們驗(yàn)證一下。

    # perf stat -e syscalls:sys_enter_read ./main  
     Performance counter stats for './main':  
                1,000,001 syscalls:sys_enter_read  
           0.006269041 seconds time elapsed  
    

    上述實(shí)驗(yàn)證明,系統(tǒng)調(diào)用確實(shí)是通過指令來進(jìn)行的。

    結(jié)論系統(tǒng)調(diào)用確實(shí)開銷蠻大的,函數(shù)調(diào)用時(shí)ns級(jí)別的,系統(tǒng)調(diào)用直接上升到了百ns,甚至是十幾u(yù)s,所以確實(shí)應(yīng)該盡量減少系統(tǒng)調(diào)用。但是即使是10us有哪些是系統(tǒng)進(jìn)程調(diào)用,仍然是1ms的百分之一,所以還沒到了談系統(tǒng)調(diào)用色變的程度,能理性認(rèn)識(shí)到它的開銷既可。

    為什么系統(tǒng)調(diào)用之間的耗時(shí)相差這么多?因?yàn)橄到y(tǒng)調(diào)用花在內(nèi)核態(tài)用戶態(tài)的切換上的時(shí)間是差不多的,但區(qū)別在于不同的系統(tǒng)調(diào)用當(dāng)進(jìn)入到內(nèi)核態(tài)之后要處理的工作不同,呆在內(nèi)核態(tài)里的時(shí)候相差較大。

    關(guān)注知乎專欄《開發(fā)內(nèi)功修煉》或搜索微信公眾號(hào)“”,收獲更多知識(shí)!

    參考資料

    整理了寫「開發(fā)內(nèi)功修煉」時(shí)參考到的電子書,想深入學(xué)習(xí)的同學(xué)可以下載。

    下載地址: /s/N7A

    提取碼: 4uqa

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有