模擬進度條

本文通過編寫模擬進度條程序來記錄一些知識點,進度條始終在同一行顯示,且不斷的增加打印*個數以表示進度增加,程序如下:

  1 #include <stdio.h>
  2 
  3 void display_progress(int num)
  4 {
  5     int i = 0;
  6 
  7     for (i = 0; i < num; i++)
  8     {
  9         printf("*");
 10     }
 11 
 12     return;
 13 }
 14 
 15 
 16 int main(void)
 17 {
 18     int i = 0;
 19 
 20     for (i = 0; i <= 100; i++)
 21     {
 22         printf("\r");
 23         display_progress(i);
 24         fflush(stdout);
 25         sleep(1);
 26     }
 27 
 28     printf("\n");
 29 
 30     return 0;
 31 }

1、回車和換行 \r\n
'\r'回車符的意思是將光標移動到當前行的開始
'\n'換行符的意思則是將光標移動到下一行

在windows系統中是通過 "\r\n"實現換行操作
在linux系統中是通過"\n"實現換行操作


2、緩衝與緩存
一直沒搞明白,緩衝和緩存是否可以混着用,我自己理解是緩衝是一種操作,用於該種操作的地方叫緩存,即緩衝區等於緩存。

(1)全緩衝 緩衝區填滿才進行實際的I/O操作
(2)行緩衝 遇到換行符時才進行實際的I/O操作,如緩衝區滿了,即便沒遇到換行符也進行I/O操作
(3)無緩衝


3、printf函數
printf是一個行緩衝函數,先寫到緩衝區,滿足條件後,纔將緩衝區刷到對應文件中,刷新緩衝區的條件如下:
1 緩衝區填滿 (printf行緩衝區大小爲1024字節)
2 遇到'\n' 或 '\r' 字符
3 調用fflush手動刷新緩衝區
4 調用scanf從緩衝區中讀取數據

滿足上面4個條件之一緩衝區就會刷新, 將數據寫入到對應的文件
當我們執行printf的進程或者線程結束的時候會主動調用fflush來刷新緩衝區,所以程序結束,也會刷新

有時候會遇到該有的打印沒有顯示,就注意下是不是printf沒有添加'\n'符號。
對與本程序而言,進度條需一直在同一行顯示,固不能有'\n'進行換行操作,數據需通過fflush手動刷新到標準輸出。



4、文件的寫同步sync
讓我想起另一個問題,記得有次往sd卡寫數據,顯示write接口已返回成功,我便拔掉了SD卡,結果查看數據並沒有寫完全。
這裏存在的問題是在UNIX系統中,write函數是把數據從進程緩衝區拷貝到內核緩衝區當中便返回了,當緩衝區滿或者內核要重用該緩衝區時,才把該緩衝區的數據排入輸出隊列,然後等到其到達隊首時,才進行實際的I/O操作。即實際的寫磁盤操作則可能在以後的某個時刻進行。這被稱爲延遲寫,這樣做的目的是減少系統調用,提高CPU的工作效率。如要及時同步磁盤文件,則可通過sync、fsync和fdatasync三個函數實現。

void sync(void);
sync函數只是將內核緩衝區的數據排入到輸出隊列就返回了,並沒有進行實際的I/O操作。系統守護進程一般每隔一段時間就會調用該函數。

int fsync(int fd);
fsync與sync不同之處在於它等待寫磁盤操作結束才返回,保證數據已同步到磁盤文件。

int fdatasync(int fd);
類似與fsync,不同之處在於只保存文件數據同步,不包括文件本身的特徵數據。


5、fflush與fsync的關係
如通過fwrite庫函數將數據寫到文件當中,數據只是先寫到了流緩衝區當中,可通過fflush只刷新位於流緩衝區中的數據,將其寫到內核緩衝區當中,並不保證及時寫到磁盤文件當中。固要及時同步還需調用fsync庫函數實現。


存在問題
上述程序在運行過程中,如縮小屏幕寬度,那麼在運行一段時間後,當屏幕寬度裝不下一行打印的時候,自動分成了兩行打印,而下一次的 “\r”操作只是回到了分2行後的第二行開頭,這時變出現非預期的打印了,這種情況我還不知道怎麼處理,如有清楚的,麻煩跟我講解下,謝謝。


參考資料
http://www.ruanyifeng.com/blog/2006/04/post_213.html (講述回車換行的來歷,建議看下評論)
http://www.2cto.com/os/201409/339460.html  (同步內核緩衝區講解)
《UNIX環境高級編程》

發佈了47 篇原創文章 · 獲贊 17 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章