這兩天在項目原有版本的基礎上增長了一段新的協議實現代碼,所以須要和平臺進行聯調。考慮到更好地進行調試,我在代碼中添加了一段相似日誌記錄的代碼,已獲取通信的報文內容和當時的環境參數內容,就是建立一個文件,使用標準IO的fopen、fprintf進行輸出記錄。可是在調試中,剛開始我就傻眼了,文件建立成功了,可是實時查看居然沒有任何數據記錄。通過半天的擔驚受怕和反覆排查,發現是被標準IO的緩衝機制擺了一道,慚愧呀。。。函數
下面給出一個示例程序,模擬個人項目程序:調試
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
int main()
{
FILE* fp=NULL;
const char *filename_1="test_fprintf.log";
const char *filename_2="test_write.log";
int fd;
fp = fopen(filename_1, "wb");
if(fp == NULL)
{
printf("open %s failed, %s\n", filename_1, strerror(errno));
return -1;
}
//setbuf(fp, NULL);
//setvbuf(fp, NULL, _IONBF, 0);
fd = open(filename_2, O_WRONLY|O_CREAT|O_EXCL, 0666);
if(fd < 0)
{
printf("open %s failed, %s\n", filename_2, strerror(errno));
return -1;
}
while(1)
{
fprintf(fp, "test fprintf.\n");
fprintf(fp, "-------test fprintf.\n");
fprintf(fp, "=======test fprintf.\n");
//fflush(fp);
write(fd, "test open.\n", sizeof("test open.\n"));
write(fd, "--------test open.\n", sizeof("--------test open.\n"));
write(fd, "--------test open.\n", sizeof("--------test open.\n"));
sleep(1);
}
return 0;
}
後臺運行上面的示例程序,而後實時查看兩個日誌文件,會發現testfrpintf.log文件一開始一直都是空的,而testwrite.log則是不斷有數據寫入,以下狀態: 日誌
我當時就是奇怪爲何文件會是空的。能夠看出標準IO會緩衝4096Bytes的數據,當達到這麼多數據時纔會進行實際的磁盤寫入,而系統調用write則是直接寫入,不進行緩衝。code
標準IO庫提供緩衝的目的是儘量減小使用read和write調用的次數,下降執行IO的時間,它提供三種類型的緩衝:string
ISO C要求下列緩衝特徵:it
不少系統默認使用下列類型的緩衝:io
固然,對於標準IO流,咱們也能夠更改緩衝類型,或者是直接刷新。ISO C中提供下面兩個函數以更改緩衝類型:table
1 |
void setbuf ( FILE *fp, char *buf); //buf爲NULL,表示關閉緩衝 |
2 |
int setvbuf ( FILE *fp, char *buf, int mode, size_t size); //成功返回0,出錯返回非0值 |
setvbuf函數中的mode參數能夠爲:_IOBUF 全緩衝, _IOLBF 行緩衝, _IONBF 不帶緩衝,若是buf爲NULL, 則標準IO庫將自動地爲該流分配適當長度(常量BUFSIZ)的緩衝區。通常而言,應由系統選擇緩衝區的長度,並自動分配緩衝區,這樣關閉流時,標準IO庫將自動釋放緩衝區。test
強制沖洗一個流,使用函數:後臺
1 |
int fflush ( FILE *fp); //成功返回0, 出錯返回EOF |
項目中我是使用這個函數解決鬱悶的。
1 |
fflush (NULL); //沖洗全部輸出流 |