亚洲免费不卡_在线视频精品_国产尤物精品_久久久久网址_久久精品91_欧美va天堂在线_狠狠入ady亚洲精品_亚洲午夜精品福利_国产精品草草_午夜精品久久99蜜桃的功能介绍

stdio 的 buffer 問題
來源:易賢網 閱讀:1885 次 日期:2015-04-03 11:23:20
溫馨提示:易賢網小編為您整理了“stdio 的 buffer 問題”,方便廣大網友查閱!

下面會涉及到一些底層的函數庫以及系統調用,不想看過程的直接跳到最后看結論好了。

一段代碼,通過 tail -f 看打的 log,發現很長時間都沒有輸出,然后突然一下子輸出了好多條,猜想可能跟 buffer 之類的有關系。這個問題其實很早就遇到過,最初以為是什么 bug,直到看到自己寫的代碼也出現類似的現象之后才決定看看是怎么回事。

先來看看下面這一小段代碼。

$ cat demo1.py

import time, sys

for i in range(50):

sys.stdout.write("test")

time.sleep(0.2)

$ python demo1.py

testtesttesttesttesttes……ttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest$

可以看到,這堆 test 字符串是等了若干秒之后一下子輸出的。

如果我們把 sys.stdout.write("test") 改為 sys.stdout.write("testn") 即加上換行符號,或者使用 print 函數來輸出,發現現象不一樣了:

$ cat demo2.py

import time, sys

for i in range(50):

sys.stdout.write("testn")

time.sleep(0.2)

$ python demo2.py

test

test

test

test

test

$ cat demo3.py

import time, sys

for i in range(50):

print "test"

time.sleep(0.2)

發現不管是 demo2 還是 demo3,屏幕上均以平均 0.2s 的頻率輸出 test 字符。

把 demo3 的 print "test" 換成 print "test",(結尾加一個半角逗號)再看看是什么現象。

再用 python3 的 print("test") 試試,嘗試加上 end 參數比如,print("test", end="n"), print("test", end="t"),print("test", end="") 再試試有什么不同的結果。

再來看一個 demo:

$ cat demo4.py

import time, sys

for i in range(50):

sys.stdout.write("test")

sys.stdout.flush()

time.sleep(0.2)

加上 sys.stdout.flush() 看看跟上面的比有什么不同的效果。

最后一個,代碼是 demo3.py,但是運行的方式不同:

$ python demo3.py > output

注意實時觀察 output 文件的大小,發現并沒有隨時間而增大,而是 demo3.py 運行結束了之后才變化的。

上面就是之前遇到的一些現象,這里面涉及到其實是 UNIX 下面的 STDIO buffer 問題。下面會深入現象揭開本質,沒時間的看最后的結論即可。

IOS C 標準定義了一套叫標準 I/O 的庫,也叫 buffered I/O,這套庫被包括 UNIX 在內的系統所實現,包括我們日常使用的眾多發行版本。而大家熟知的 open, read, write, lseek, close 這些 I/O 系統調用函數則是 POSIX 定義的,他們通常稱為 unbuffered I/O,就是為了跟標準 I/O 庫作出區分。這些底層的系統調用函數,大多都是圍繞 fd 展開,而標準 I/O 則是圍繞著 STREAM 展開,標準 I/O 庫其實可以理解為對系統 I/O 函數的封裝,因為標準 I/O 庫最終還是要調用對應的這些系統 I/O 函數,可以通過 fileno(FILE *FP) 獲取到 STREAM 對應的 fd。

為什么說標準 I/O 庫是 buffered I/O 了,因為他會自動的幫你處理 buffer 分配以及 I/O chunks 的選擇,這樣就不再需要為選擇 block size 而操心了,這個在使用系統 I/O 調用的時候無法避免,比如 read/write 都需要考慮 buffer 地址以及讀取寫入的 buffer size,通常你需要在調用 read 時候定義一個 buffer size 的宏:

# define BUFFSIZE 4096

buffered I/O 的主要目的就是為了降低 read/write 這類的系統調用以及自動的為程序分配 buffer。但是他分為了下面三種類似的 buffering:

1. full buffer,當標準 I/O buffer 滿了時候發生一次 flush 操作,可以調用 fflush() 來完成,他將 buffer 里面的數據 flush 到內核緩沖區中。

2. line buffer,遇到換行符(一般就是 "n") 也就是寫完一行的時候發生一次 flush,

3. unbuffered,有多少讀寫多少。

Linux 一般是這樣實現的:

1. stderr 是 unbuffered,這會讓錯誤信息及時的出現。

2. stdin/stdout stream 如果不跟終端相關聯,比如 pipe,redirect,fopen 打開的文件,則是 full buffer;如果跟終端相關聯,則是 line buffer

上面這兩條規則其實就是速度跟系統之間的一個 tradoff,很好理解。

可以通過 setbuf/setvbuf 來修改 buffer 的模式,具體的使用方式 man 2,需要注意的是,這兩個函數要在 stream 打開之后其余 I/O 操作之前調用,讓然,如果你需要做一些特殊的事情,完全可以在昨晚某些 I/O 操作之后再調用,比如下面要舉的第二個 demo。setvbuf 比 setbuf 有更大的優勢,比如可以修改 buffer 的大小等等。

關于 STREM 對應的 buffer 類型,其大小可以通過這段代碼來做一個驗證,比如我的機器的幾個 buffer size 都是 8KB。

而 int fflush(FILE *fp) 這個函數就是解決我們上面問題的核心了,該函數會將當前 STREAM 中的數據 flush 到內核緩沖區,如果 fp 是 NULL,則 stdout 流被 flush 一次。準確的說,fflush 只能用于輸出流,而不能用于輸入流,具體的原因見這里。

這里的一個 demo 很好的解釋了 fflush/setvbuf 做的事情,嘗試把 setvbuf 中的 size_t size 參數從原先的 1024 調小到 20 試試看。

很明顯,通過這種 buffer 的方式,把一部分的寫先 buffer 起來然后統一調用一次系統調用,可以大量的減少 user space 跟 kernel space 之間的切換。

可能會有人想到 fsync 這個系統調用,它跟 fflush 做的事情好像是一樣的,其實仔細辨別的,二者做的事情根本不在一個平面上。

fflush(FILE *stream) 作用的是 FILE*,對于 stdout 來說,他是將標準 IO 流的 buffer 從用戶空間 flush 到內核緩存中。這也是調用 exit 要做的事情。

fsync(int fd) 控制的是何時將 data&metadata 從內核緩沖區 flush 到磁盤中,他的傳入參數是一個 fd。對 fsync 來說,FILE* 是透明的也就是所他并不知道 FILE* 的存在,一個是在 user space 一個是在 kernel space。

所以,如果我們不想有 full/line buffer 而是盡可能快的獲取到輸出流的話,就需要通過調用 fflush(stdout) 指明。

上面解釋的僅僅是 C 的,對于 Python 而言,底層調用的東西幾乎一樣,Python 它自己通過 C 實現了 fflush(),具體的代碼可以看這里。其實不單單是 fflush,不少包括 read/write 在內的底層調用 Python 都是用 C 實現的。

對用到 Python 的 fflush 則是 sys.stdout.flush()。

不管是 fflush() 還是 sys.stdout.flush(),都需要對立即返回的 stdout 手動的調用,比較麻煩。所幸的,上面提到的 setvbuf 就可以直接幫我們做這件事,在 stream 打開后調用 setvbuf() 即可,其 mode 參數可以選擇下面三種:

1. _IOLBF,line buffer

2. _IOFBF, full buffer

3. _IONBF,no buffer

要完全禁用的話按照下面這種方式調用:

setvbuf(stdout, 0, _INNBF, 0);

對應到 python 的,至少還有下面的幾種方式可以避免此類問題:

1. 直接關閉 stdout 的 buffer,類似 setvbuf:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

2. 有個比較 ugly 的方式,把輸出流改到 stderr 上,這樣不管什么時候都能保證盡快的輸出。

3. 直接腳本的時候加上 -u 參數。但是需要注意下,xreadlines(), readlines() 包含一個內部 buffer,不受 -u 影響,因此如果通過 stdin 來遍歷會出現問題,可以看看這兩個連接提供的內容(1, 2)。

4. 將其 stream 關聯到 pseudo terminal(pty) 上,script 可以做這事情的:

script -q -c "command1" /dev/null | command2

或者通過 socat 這個工具實現,

再來看個跟 pipe 相關的問題, 這個命令常?;剀囍鬀]有反應:

$ tail -f logfile | grep "foo" | awk {print $1}

tail 的 stdout buffer 默認會做 full buffer,由于加上了 -f,表示會調用 fflush() 對輸出流進行 flush,所以 tail -f 這部分沒什么問題。關鍵在 grep 的 stdout buffer,因此它存在一個 8KB stdout buffer,要等該 buffer 滿了之后 awk 才會接收到數據。awk 的 stdout buffer 跟終端相關聯,所有默認是 line buffer。怎么解決這個問題了,其實 grep 提供了 –line-buffered 這個選項來做 line buffer,這會比 full buffer 快的多:

tail -f logfile | grep –line-buffered "foo" | awk {print $1}

除了 grep,sed 有對應的 -u(–unbuffered),awk(我們默認的是 mawk) 有 -W 選項,tcpdump 有 -l 選項來將 full buffer 變成 line 或者 no buffer。

不僅僅是 stdin/stdout/stderr 有 buffer 問題,pipe 同樣有 buffer 的問題,相關的文檔可以看這里(1, 2)。

上面的方式都涉及到了具體的函數調用,修改參數的不具有普遍原理,對于普通用戶來說,不大可能這么操作。其實 coreutils 已經給我們提供了一個叫 stdbuf 的工具。expect 還提供了一個叫 unbuffer 的工具,通過它可以將輸出流的 buffer 給禁止掉,另外,在 pipe 的應用中,可能會出現一些問題,具體的 man 一下。因此,上面的問題可以更具有普遍性:

tail -f logfile | stdbuf -oL grep "foo" | awk {print $1}

看到這里最上面的幾個問題現在應該非常容易回答了。

ref:

更多信息請查看IT技術專欄

更多信息請查看技術文章
易賢網手機網站地址:stdio 的 buffer 問題
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點

版權所有:易賢網

亚洲免费不卡_在线视频精品_国产尤物精品_久久久久网址_久久精品91_欧美va天堂在线_狠狠入ady亚洲精品_亚洲午夜精品福利_国产精品草草_午夜精品久久99蜜桃的功能介绍
亚洲综合激情| 噜噜噜躁狠狠躁狠狠精品视频| 激情久久中文字幕| 怡红院精品视频在线观看极品| 国产精品二区在线| 中文日韩在线| 国产精品xvideos88| 日韩亚洲精品在线| 欧美日韩一区二区三| 国产日韩一区欧美| 亚洲视频一区| 老牛国产精品一区的观看方式| 亚洲激情社区| 欧美精品一区二区三区久久久竹菊| 亚洲区第一页| 国产精品啊v在线| 性刺激综合网| 一区二区三区视频在线播放| 欧美特黄一区| 你懂的国产精品| 亚洲一区二区精品在线观看| 国内久久精品| 欧美激情一级片一区二区| 国产精品美女久久久| 极品裸体白嫩激情啪啪国产精品| 媚黑女一区二区| 国产精品日韩高清| 亚洲天堂成人| 欧美不卡一区| 亚洲黄色在线| 精品99视频| 欧美日韩国产欧| 欧美成熟视频| 久久久久久亚洲精品不卡4k岛国| 日韩视频精品在线观看| 国产精品v日韩精品v欧美精品网站| 亚洲一区激情| 99视频一区| 亚洲激情综合| 亚洲精品无人区| 亚洲精品四区| 在线综合亚洲| 亚洲欧美精品在线观看| 亚洲一区三区在线观看| 亚洲欧美日韩国产综合精品二区| 国产日韩一区二区三区| 国产欧美日韩综合一区在线观看| 日韩亚洲国产精品| 亚洲经典视频在线观看| 亚洲人成免费| 亚洲免费网址| 久久国产一区二区| 欧美韩日精品| 激情综合亚洲| 亚洲国产精品一区在线观看不卡| 久久一区亚洲| 欧美在线免费一级片| 久久最新视频| 欧美日韩在线一二三| 亚洲午夜精品久久久久久app| 国产精品二区影院| 亚洲激情av| 亚洲欧美春色| 欧美精品成人| 亚洲精一区二区三区| 国产伦精品一区二区三区四区免费| 国产亚洲一级| 欧美日本亚洲| 中文在线一区| 欧美1区3d| 亚洲三级影院| 久久久久久久高潮| 在线成人欧美| 久久亚洲精品伦理| 亚洲高清不卡| 久久久综合香蕉尹人综合网| 欧美日韩一卡| 亚洲欧美久久| 亚洲精美视频| 欧美激情日韩| 国产精品一区视频| 欧美日韩综合精品| 国产午夜精品一区二区三区欧美| 每日更新成人在线视频| 欧美天堂亚洲电影院在线观看| 91久久在线| 欧美国产精品| 国产亚洲二区| 亚洲成人原创| 欧美日韩一区在线播放| 国产视频精品网| 精品动漫一区| 欧美激情五月| 国产免费成人| 91久久国产自产拍夜夜嗨| 狂野欧美一区| 午夜在线一区| 亚洲美女一区| 韩国欧美一区| 欧美久久影院| 亚洲欧美亚洲| 欧美一区亚洲| 久久婷婷麻豆| 久久午夜视频| 麻豆精品传媒视频| 久久成人精品| 久久成人免费| 国产精品一区二区你懂得| 亚洲精品在线免费| 亚洲日本激情| 亚洲精一区二区三区| 精久久久久久| 亚洲黑丝一区二区| 在线精品福利| 亚洲区一区二| 在线综合亚洲| 国产女主播一区二区| 国产精品久久久久久久久久直播| 亚洲国产日韩综合一区| 永久久久久久| 在线一区免费观看| 亚洲欧美日本日韩| 奶水喷射视频一区| 午夜国产精品视频| 欧美日韩在线精品| 亚洲国产免费看| 一本色道久久精品| 欧美一级播放| 欧美日韩免费观看一区| 黄色在线一区| 在线精品亚洲| 国产欧美高清| 久久美女性网| 激情综合电影网| 国产亚洲激情| 久久综合九色99| 狠狠综合久久av一区二区老牛| 亚洲人体大胆视频| 久久国产直播| 在线欧美三区| 久久久久看片| 亚洲国产精品第一区二区三区| 在线综合亚洲| 你懂的视频一区二区| 激情视频一区二区| 国产精品色网| 国内在线观看一区二区三区| 日韩午夜高潮| 欧美片第1页综合| 国产日韩三区| 合欧美一区二区三区| 国产精品美女久久久浪潮软件| 狂野欧美性猛交xxxx巴西| 激情成人综合| 久久精品一区| 中文国产一区| 精品动漫3d一区二区三区免费| 一区二区精品在线观看| 欧美精品一区二区视频| 国产精品久久国产愉拍| 欧美日韩高清在线一区| 国产日韩一区欧美| 狠色狠色综合久久| 欧美 日韩 国产 一区| 99精品国产在热久久| 欧美午夜不卡影院在线观看完整版免费| 亚洲精品在线视频观看| 欧美久色视频| 久久国产精品毛片| 国产视频欧美| 在线国产欧美| 亚洲午夜电影| 欧美日韩综合网| 毛片一区二区| 亚洲一区二区在线看| 91久久国产综合久久蜜月精品 | 午夜亚洲影视| 99在线热播精品免费99热| 韩国一区二区三区在线观看| 老司机精品导航| 久久精品主播| 久久精品中文字幕一区二区三区| 国产伦理一区| 男人的天堂亚洲在线| 欧美亚洲专区| 久久亚洲午夜电影| 欧美国内亚洲| 红桃视频国产精品| 亚洲国产精品一区| 99国产一区| 亚洲永久网站| 欧美在线高清| 国产精品国产精品| 亚洲东热激情| 国产精品免费区二区三区观看| 国产精品免费看| 久久亚洲一区| 亚洲一级影院| 国产美女诱惑一区二区| 亚洲一区二区成人| 久久综合福利| 狠狠爱www人成狠狠爱综合网| 狠狠色综合网| 一本色道久久综合亚洲精品不| 一区二区毛片| 免费日韩视频| 欧美日韩亚洲在线| 激情91久久| 亚洲精品一区二区三区av| 国产午夜精品一区二区三区欧美| 国产精品久久久对白| 久久精品一本| 亚洲高清在线| 亚洲尤物精选| 国产精品观看| 国产精品制服诱惑| 欧美视频亚洲视频| 宅男噜噜噜66国产日韩在线观看| 西西人体一区二区| 亚洲午夜电影| 欧美亚洲网站| 亚洲黄色成人久久久| 亚洲欧美精品| 亚洲性色视频| 美女精品一区| 91久久视频| 欧美精品99| 先锋亚洲精品| 亚洲黄页一区| 欧美另类亚洲| 亚洲欧美日韩在线观看a三区| 欧美午夜精品久久久久免费视| 亚洲精品黄色| 欧美日韩一区二区三区在线视频| 国产精品久久久久久久免费软件 | 国产精品毛片va一区二区三区| 久久大逼视频| 一本色道久久综合亚洲精品婷婷| 久久综合久久久| 一本色道久久99精品综合| 欧美激情视频一区二区三区在线播放| 亚洲麻豆视频| 欧美日韩伊人| 欧美激情一区| 美女精品在线| 亚洲一区二区三区色| 亚洲高清视频一区二区| 欧美日韩精品一区| 久久婷婷国产综合尤物精品| 一本色道久久综合| 亚洲国产精品久久久久婷婷老年 | 亚洲国产高清一区二区三区| 久久免费高清| 亚洲免费中文| 亚洲一区二区三区精品动漫| 亚洲大胆在线| 尤物在线精品| 黑人一区二区| 亚洲视频日本| 影音先锋亚洲一区| 1024成人| 亚洲国产片色| 亚洲免费观看| 久久最新视频| 亚洲午夜精品福利| 欧美天天视频| 国产精品hd| 国语对白精品一区二区| 欧美日韩三区| 黑人一区二区| 亚洲激情综合| 亚洲深夜福利| 国产伦精品一区二区三区四区免费| 91久久中文| 国产欧美亚洲一区| 亚洲女优在线| 久久久久久自在自线| 老司机精品导航| 欧美啪啪一区| 精品999网站| 在线日韩视频| 亚洲少妇自拍| 久久久精品国产一区二区三区| 久久精品一区二区国产| 你懂的国产精品永久在线| 欧美精品日本| 亚洲国产一区二区三区高清| 亚洲免费激情| 久久福利毛片| 国产精品大片| 亚洲日本国产| 久久精品人人做人人爽电影蜜月| 老司机午夜精品视频| 国内精品久久久久久久97牛牛 | 国产精品mm| 亚洲精品影院| 欧美fxxxxxx另类| 亚洲黄色影片| 女主播福利一区| 亚洲精品国产系列| 巨乳诱惑日韩免费av| 亚洲高清在线| 欧美a级在线| 亚洲少妇一区| 国内精品福利| 欧美专区18| 亚洲精品欧洲| 欧美日韩在线观看一区二区三区| 99re6热在线精品视频播放速度 | 国产欧美日韩综合一区在线播放| 亚洲欧美日韩精品综合在线观看| 欧美aⅴ99久久黑人专区| 亚洲美女黄网| 国内精品亚洲| 久久综合激情| 国产精品日韩一区二区 | 国产亚洲精品自拍| 狠久久av成人天堂| 久久青青草综合| 亚洲综合日韩| 夜久久久久久| 亚洲国产精品久久久久久女王| 久久久99爱| 亚洲一区欧美激情| 亚洲精品欧美| 亚洲婷婷免费| 午夜精品区一区二区三| 午夜宅男久久久| 99re热精品| 亚洲区第一页| 亚洲伦理精品| 日韩午夜一区| 亚洲美女网站| 99国产精品久久久久久久| 国精品一区二区| 国产精品s色| 国产精品magnet| 欧美区日韩区| 欧美a级一区| 欧美日韩国产色综合一二三四| 久久久久欧美| 午夜精品久久99蜜桃的功能介绍| 蜜桃伊人久久| 欧美在线一二三区| 欧美性久久久| 黄色精品网站| 亚洲国产午夜| 在线亚洲欧美| 亚洲欧美日韩精品在线| 久久久久成人精品免费播放动漫| 午夜亚洲伦理| 你懂的一区二区| 狠久久av成人天堂| 99国产精品久久久久老师| 在线一区日本视频| 免费亚洲一区| 欧美黄免费看| 亚洲二区在线| 国产欧美一区二区三区另类精品| 国产一级精品aaaaa看| 亚洲综合不卡| 欧美日韩一区在线视频| 在线欧美亚洲| 先锋影音一区二区三区| 老妇喷水一区二区三区| 欧美激情综合色综合啪啪| 极品av少妇一区二区| 99国产精品视频免费观看一公开 | 亚洲国产日韩欧美| 国产午夜精品一区二区三区欧美 | 久久久久久久波多野高潮日日| 久久一区二区三区四区五区 | 亚洲一区二区三区高清不卡| 久久av在线| 一区精品在线| 蜜桃av噜噜一区二区三区| 狠狠色噜噜狠狠色综合久| 国产精品入口| 亚洲五月婷婷| 久久亚洲国产精品一区二区| 在线日韩av| 欧美va天堂在线| 国产欧美成人| 韩国精品一区二区三区| 亚洲欧美日韩国产一区二区| 国产精品高清一区二区三区| 国产精品丝袜xxxxxxx| 欧美日韩三区四区| 亚洲欧美日韩在线观看a三区| 国内自拍一区| 欧美不卡在线| 亚洲专区免费| 亚洲精品乱码| 欧美亚洲不卡| 欧美88av| 久久婷婷国产综合尤物精品| 国产欧美日本| 亚洲免费久久| 亚洲日本激情| 伊人成年综合电影网|