女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

深度解讀Linux內核printf冰山的秘密

Linux閱碼場 ? 來源:csdn ? 作者:dog250 ? 2020-08-31 15:28 ? 次閱讀

近日在一次測試Linux內核路由查找算法的過程中,發現一個printf語句竟然能將性能降低2/3。當然,使用“竟然”一詞并不意味著這個問題是第一次發現,我的想法是,把它記錄下來,讓沒有經驗的同學對printf知其所以然,同時導出我對“性能攸關”的這類算法中記錄日志的一個觀點。

聲明

我不會把大段的源代碼貼在文章中,而只是希望能通過闡述原理把我的意思表達清楚。誠然,作為程序員沒有代碼好像一切都會很虛,不過同樣的,也是因為代碼,總是會把人逼進死胡同,代碼只是一種實現,理解了原理,作為一個懂編程的程序員,任何人都可以寫出一個自己的實現。
我會給出原理圖,但是這圖決不是我憑空想象的,來源在哪?當然是UNIX的相關標準以及Linux的具體實現代碼。既然原理來自于Linux的代碼,為何不貼出來分析一下呢?要知道,代碼隨著Linux的內核版本,C庫的版本以及應用程序的版本變化而變化,不變的是思想!UNIX歷經幾十年,其思想不還在指導著千千萬萬的程序員嗎?另外,有誰會去通讀Linux內核代碼呢?對于大多數的人而言,如果想知道printf或者任何其它的接口的原理,肯定不會去擺開架勢做出一副要先了解Linux內核架構,C庫架構作為前置知識,然后去跟蹤調試其實現。在以上這個過程中,你會把大量的精力消耗在理解不相關的內容上,比如函數調用關系,層層嵌套的條件語句,或者調試器怎么使用,諸如此類。

關于printf

printf是一個接口,跟UNIX標準IO的write系統調用類似,但是更像C庫的fwrite,因為同系列的函數中還有一個fprintf(至于同系列其它的函數,請自行man)。printf和fwrite的區別在于兩點:

1.它可以格式化輸出,如果用fwrite,它接受的是一個固定的buffer,你不得不在調fwrite之前先使用sprintf之類的函數格式化buffer;

2.它免除了你的fopen-fwrite-fclose這個序列的調用,因為它直接將格式化的內容寫入UNIX進程自然打開的1號文件描述符,即標準輸出。

既然printf寫入了標準輸出,那么接下來就要定義什么是標準輸出。在早期UNIX年代,人們在終端或者偽終端操作機器,那時的輸入基本都是鍵盤,磁帶更古老的東西,而輸出就是一個計算結果,需要展示出來給人看的那種,一般為終端屏幕,也可以是一條紙帶,那么程序怎么知道輸入和輸出到底是什么呢?這就需要程序明確指定。UNIX的“一切皆文件”思想以及“分離抽象”思想徹底改變了這一切。

UNIX定義了抽象文件描述符0,1,2分別為標準輸入,標準輸出,標準錯誤輸出。至于它們到底對應什么設備,你可以在程序初始化的時候顯式重定向到任意設備,也可以在外部shell做類似的重定向,這樣就把指明設備這件事從程序分離了出來。

我為什么不統一說一下fwrite調用對程序性能的影響呢?因為該調用之前你必須執行fopen,而fopen的一個參數明確表示了你希望寫入的對象是什么,這就不會帶來異議,畢竟如果你非要在性能測試的時候寫CF卡,那也是你愿意。printf就不同了,它對效率的影響取決于標準輸出是什么以及你是如何重定向標準輸出的,所謂的標準輸出并不是真實的設備,它只是一個抽象層,具體如何解釋標準輸出,還要依靠外部。

數據都去哪兒了

我以下面這個超級小的程序來說明printf的時候,數據都去哪了:

#include #include 
int main(int argc, char **argv){        int i = 0;        int c = atoi(argv[1]);        for(; i < c; i++) {                printf("############  %d
", i);        }        return 0;}

我先給出結果:
1.在/dev/tty1上直接執行time ./test 1000
...
######### 995
######### 996
######### 997
######### 998
######### 999

real 0m0.414s
user 0m0.003s
sys 0m0.411s


2.在/dev/tty1上執行time ./test 1000 >/dev/tty2
real 0m0.007s
user 0m0.003s
sys 0m0.007s

3.在SecureCRT上執行time ./test 1000
...
######### 997
######### 998
######### 999

real 0m0.010s
user 0m0.002s
sys 0m0.003s


4.在SecureCRT上執行time ./test 100000 >/dev/tty1,此時不切換tty
...
等了幾秒,無結果,于是在鍵盤按下Alt-F2,切換到第二個tty,馬上顯示出了結果:
real 0m4.276s
user 0m0.066s
sys 0m4.204s


5.在tty1上執行time ./test 100000 >/dev/tty2:
real 0m0.499s
user 0m0.081s
sys 0m0.410s


6.在tty1上執行time ./test 100000 >/dev/null
real 0m0.030s
user 0m0.028s
sys 0m0.001s

通過以上的結果數據,我們可以得到以下的結論:

a.對于tty終端而言,如果當前終端不是寫入的終端,那么開銷主要在內核態,且開銷不是很大;

b.對于tty終端而言,如果當前終端是寫入的終端,那么開銷主要在內核態,且開銷很大;

c.對于不管是tty還是遠程的pty終端,寫入/dev/null的開銷主要在用戶態,開銷不大;

d.對于pty遠程終端(/dev/pts/X),不管寫入的是不是當前的pty終端,開銷主要在內核態,且開銷不是很大

e.對應上面的結果和結論,下面給出一幅圖解,詳細解釋一下printf冰山下面的秘密:

我想上圖已經很清楚了,如果不懂什么叫行規程(也叫線路規程)的話,請閱讀《UNIX環境高級編程》的終端和偽終端章節,簡單來說,它就是一個中間層,用來適配VFS接口和底層的具體驅動,比如解釋和處理控制字符等。從上面的圖中,我們可以看出,主要的開銷幾乎都集中在底層,而底層卻偏偏是我們不能控制或者很難控制的。之所以上面的測試例子中ssh登錄的終端對test性能的測試效果良好,但是那是因為網絡環境好,你在一個64kbps相隔5k公里的線路上試一下。

小小的printf下面竟然藏著如此多的內容,并且很可能就是它成了你的程序的性能瓶頸,因為最底層的影響因素往往是不可控的。那么是不是就是意味著我要建議大家從來不用printf打印呢?或者說干脆就不要用標準輸出呢?并不是這樣。但是為何不把打印這種事交給本機的另一個進程呢?事實上,幾乎所有的需要記錄日志的系統都是這么做的,而syslog則迎合了這個思想。這種思想的背后就是“用可控制的一次IPC替換不可控制冰山之下的茫茫深海”

關于日志記錄

日志記錄一直都是“薛定諤貓”式的東西,因為日志記錄作為一段代碼,它已經是程序的一部分,不可能獨立地觀察程序的行為,如果說用鏡像系統的話,那么這種行為就是被動的,你不得不鏡像每一條指令,以發現一些關鍵的信息,要想主動記錄關鍵事件,必須用日志系統。打印日志可以方便信息獲取和審計,但是代價有時也是高昂的:

1.你要設計一套日志回滾系統,防止存儲空間被撐爆;

2.你要讓日志記錄盡快完成,不能降低關鍵路徑的性能;

3.你要反復調試代碼,確保日志記錄的緩沖區不會溢出;

4.為了讓日志更短,語言能力不好的人組織的日志就像電報一樣難以理解。

我認為,日志記錄應該遵循以下的原則:

1.除非必須要把事件發生的時間記錄下來,否則就用計數器代替日志記錄,一系列的事件映射成一系列的計數器,由用戶決定什么時候查看事件發生了。事實上,Linux的網絡子系統就是用的這種方式,所有的/proc/net/netstat就是這個查看接口。

2.一定要有一個日志級別控制選項,用戶可以決定是否記錄日志,以及記錄的日志詳細到什么程度。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11465

    瀏覽量

    212840
  • Printf
    +關注

    關注

    0

    文章

    84

    瀏覽量

    14102

原文標題:printf的歸宿-數據打印到哪兒了

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    如何配置和驗證Linux內核參數

    Linux系統運維和性能優化中,內核參數(sysctl)的配置至關重要。合理的參數調整可以顯著提升網絡性能、系統穩定性及資源利用率。然而,僅僅修改參數是不夠的,如何驗證這些參數是否生效同樣關鍵。
    的頭像 發表于 05-29 17:40 ?182次閱讀

    樹莓派4 性能大比拼:標準Linux與實時Linux 4.19內核的延遲測試

    引言本文是對我之前關于RaspberryPi3同一主題的帖子的更新。與之前的帖子一樣,我使用的是隨Raspbian鏡像提供的標準內核,以及應用了RT補丁的相似內核版本。對于實時版,我
    的頭像 發表于 03-25 09:39 ?259次閱讀
    樹莓派4 性能大比拼:標準<b class='flag-5'>Linux</b>與實時<b class='flag-5'>Linux</b> 4.19<b class='flag-5'>內核</b>的延遲測試

    2025年常用實時Linux系統深度評測

    1、PREEMPT-RT - 特性: ?- 實時性:通過內核補丁實現搶占式調度,響應延遲處于毫秒級別,能夠滿足一般實時應用的需求。 ?- 兼容性:與標準Linux內核高度兼容,支持廣泛的硬件平臺
    的頭像 發表于 03-06 10:57 ?565次閱讀

    騰訊云內核團隊修復Linux關鍵Bug

    騰訊云操作系統(Tencent OS)內核團隊近日在Linux社區取得了顯著成果。他們提交的兩項改進方案,成功解決了自2021年以來一直困擾眾多一線廠商,并在近期讓多個Linux頂級
    的頭像 發表于 12-31 10:58 ?607次閱讀

    stdio.h實現了printf函數?

    我們平時包含的 stdio.h 頭文件,里面是不是實現了 printf 函數? 為什么會有這個疑問?因為每次使用 printf,就得包含 stdio.h ,這就導致很多同學誤以為,stdio.h
    的頭像 發表于 12-18 10:28 ?543次閱讀

    周亞輝的朋友圈,揭開潛藏在AI冰山下的秘密

    2024年的滿分AI公司,和它們潛藏在冰山下的秘密
    的頭像 發表于 11-29 09:22 ?2482次閱讀
    周亞輝的朋友圈,揭開潛藏在AI<b class='flag-5'>冰山</b>下的<b class='flag-5'>秘密</b>

    4G模組加解密藝術:通用函數的深度解讀

    今天是對加解密通用函數的深度解讀,我將詳細講解,建議收藏,不可錯過。
    的頭像 發表于 11-12 09:58 ?568次閱讀
    4G模組加解密藝術:通用函數的<b class='flag-5'>深度</b><b class='flag-5'>解讀</b>

    deepin社區亮相第19屆中國Linux內核開發者大會

    中國 Linux 內核開發者大會,作為中國 Linux 內核領域最具影響力的峰會之一,一直以來都備受矚目。
    的頭像 發表于 10-29 16:35 ?839次閱讀

    深度解析linux HID核心

    linux內核中,HID核心是完成HID功能的關鍵組件,如果內核支持HID,在啟動過程中,則會對HID進行初始化,完成該操作的函數是hid_init(),實現在/drivers/hid/hid-core.c中。
    的頭像 發表于 09-29 17:04 ?1095次閱讀
    <b class='flag-5'>深度</b>解析<b class='flag-5'>linux</b> HID核心

    詳解linux內核的uevent機制

    linux內核中,uevent機制是一種內核和用戶空間通信的機制,用于通知用戶空間應用程序各種硬件更改或其他事件,比如插入或移除硬件設備(如USB驅動器或網絡接口)。uevent表示“用戶空間
    的頭像 發表于 09-29 17:01 ?1697次閱讀

    深度解析linux時鐘子系統

    linux內核中實現了一個CLK子系統,用于對上層提供各模塊(例如需要時鐘信號的外設,USB等)的時鐘驅動接口,對下層提供具體SOC的時鐘操作細節。
    的頭像 發表于 09-29 16:46 ?1147次閱讀
    <b class='flag-5'>深度</b>解析<b class='flag-5'>linux</b>時鐘子系統

    linux驅動程序如何加載進內核

    Linux系統中,驅動程序是內核與硬件設備之間的橋梁。它們允許內核與硬件設備進行通信,從而實現對硬件設備的控制和管理。 驅動程序的編寫 驅動程序的編寫是Linux驅動開發的基礎。在編
    的頭像 發表于 08-30 15:02 ?980次閱讀

    Linux內核測試技術

    Linux 內核Linux操作系統的核心部分,負責管理硬件資源和提供系統調用接口。隨著 Linux 內核的不斷發展和更新,其復雜性和代碼規
    的頭像 發表于 08-13 13:42 ?922次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>測試技術

    Linux內核中的頁面分配機制

    Linux內核中是如何分配出頁面的,如果我們站在CPU的角度去看這個問題,CPU能分配出來的頁面是以物理頁面為單位的。也就是我們計算機中常講的分頁機制。本文就看下Linux內核是如何管
    的頭像 發表于 08-07 15:51 ?569次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>中的頁面分配機制

    歡創播報 華為宣布鴻蒙內核已超越Linux內核

    1 華為宣布鴻蒙內核已超越Linux內核 ? 6月21日,在華為開發者大會上, HarmonyOS NEXT(鴻蒙NEXT)——真正獨立于安卓和iOS的鴻蒙操作系統,正式登場。這是HarmonyOS
    的頭像 發表于 06-27 11:30 ?1166次閱讀