%20%E6%AF%94%20getc()%20%E6%85%A2%EF%BC%9F%20.png)
為什麼read
比 慢getc
?
例如,這個:
for (;;) {
chr++;
amr=read(file1, &wc1, 1);
amr2=read(file2, &wc2, 1);
if (wc1 == wc2) {
if (wc1 == '\n')
line++;
if (amr == 0) {
if (eflg)
return (1);
return (0);
}
continue;
}
比那慢:
for (;;) {
chr++;
c1 = getc(file1);
c2 = getc(file2);
if (c1 == c2) {
if (c1 == '\n')
line++;
if (c1 == EOF) {
if (eflg)
return (1);
return (0);
}
continue;
}
getc
使用read
系統調用,為什麼會慢呢?
答案1
由於 getc() 在傳回讀取的資料之前對其進行緩衝,因此對 的呼叫getc()
不一定會導致對read()
.read()
是一個系統調用,它比普通函數調用需要更長的時間來完成,因為核心有更多的操作要做。當你進入核心空間時,它會改變你的堆疊,保存所有上下文,處理要屏蔽的中斷,而在另一端,當它完成時,它會恢復上下文,中斷,將你的用戶空間堆疊放回去。這就是為什麼getc() 是首選的原因,因為如果您已經有可用的緩衝數據,它可以節省大量開銷。
答案2
歸根結底,磁碟讀取是面向區塊的:要從磁碟讀取單一位元組,硬體最終會讀取一個位元組區塊(512 或 1024 或某個數量),緩衝所有這些,並將其傳遞給核心。如果您從檔案的區塊 0 讀取檔案的位元組 0,請做一些工作,然後從檔案讀取位元組 1,核心最終可能會再次讀取檔案的區塊 0。再次針對位元組 2,再次針對位元組 3。
每次read()
呼叫也必須將 CPU 從使用者態變更為核心態。記憶體映射至少會改變。可能還會發生很多其他不那麼明顯的事情。這也需要時間。
系統read()
呼叫會變更 CPU 狀態,並且可能需要磁碟 I/O。getc()
可以在用戶空間緩衝整個磁碟區塊(或更多),因此可能 512 呼叫會getc()
導致核心讀取單一磁碟區塊,並進行單一狀態變更。如果您查看,stdio.h
您會發現一個常數宏,該常數應該是對磁碟上檔案或系統呼叫的BUFSIZ
有效(磁碟區塊倍數)大小。read()
write()