嵌入式調試printf重定向到文件

 
除了人工的分析之外,最簡單最直接的調試方法要算printf了。不過,我們這裏推薦使用的並不是初學C語言時使用的函數int printf(const char *format, ...),而是稍微複雜一點的fprintf()函數,因爲它更方便我們之後重定向錯誤輸出信息到指定的設備。fprintf()函數的原型如下:

int fprintf(FILE *stream, const char *format, ...)

可以看到,它與printf()函數相比多出來了第一個參數FILE *stream,其意義是將打印的內容輸出到文件流指針stream指向的流。所謂流,通常是指程序輸入或輸出的一個連續的字節序列,設備(例如鼠標、鍵盤、磁盤、屏幕、調制解調器和打印機)的輸入和輸出都是用流來處理的,在C語言中,所有的流均以文件的形式出現——不一定是物理磁盤文件,還可以是對應於某個輸入/輸出源的邏輯文件。C語言提供了5種標準的流,你的程序在任何時候都可以使用它們,並且不必打開或關閉它們。以下列出了這5種標準的流。
------------------------------------------------
    名稱          描 述             例 子
------------------------------------------------
    stdin        標準輸入             鍵盤
    stdout       標準輸出             屏幕
    stderr       標準錯誤              屏幕
    stdprn       標準打印機          LPT1端口
    stdaux       標準串行設備       COM1端口
------------------------------------------------
    其中,stdprn和stdaux並不總是預先定義好的,因爲LPT1和COM1端口在某些操作系統中是沒有意義的,而stdin,stdout 和stderr總是預先定義好的。此外,stdin並不一定來自鍵盤,stdout也並不一定顯示在屏幕上,它們都可以重定向到磁盤文件或其它設備上。我們在頭文件stdio.h中可以找到stdin,stdout 和stderr的定義如下:

/* Standard streams. */
extern struct _IO_FILE *stdin;      /* Standard input stream. */
extern struct _IO_FILE *stdout;     /* Standard output stream. */
extern struct _IO_FILE *stderr;     /* Standard error output stream. */

 
在使用fprintf()函數時,通常我們可以將第一個參數設爲stdout或者stderr,打印出錯調試信息的時候則推薦使用stderr而不是stdout,這是一種慣例,同時也由於內核在處理stdout和stderr時的優先級不一樣,後者的優先級要高一些,因此有時候如果程序異常退出時,stderr能得到輸出,而stdout就不行。
printf(...) 實際上相當於fprintf(stdout, ...),這也是爲什麼我們不推薦使用它的原因。在輸出調試信息的時候,我們推薦使用fprintf(stderr, …),或者使用某個指定的文件流fprintf(some_stream, …)。
那麼具體如何在必要的時候重定向fprintf()中的調試信息呢?來看看下面的一些方法:

當調試信息的量比較大,需要一些時間或者其他輔助工具來搜索過濾時,僅僅利用顯示屏幕來輸出調試信息是不夠的,這時我們經常將這些信息輸出到所謂的日誌文件(log)中,之後再仔細的分析log文件來發現問題。
Ø       利用ShellI/O重定向
簡單的寫log方法可以通過shell的I/O重定向機制來實現,比如下面的代碼:

     1 #include <stdio.h>

 
     2
     3 int main()
     4 {
     5      fprintf(stdout, "This is a standard output info!\n");
     6      fprintf(stderr, "This is a standard error output info!\n");
     7      return 0;
     8 }

 

 
在默認條件下,編譯運行的結果是打印信息都輸出在屏幕上:

$ gcc fprint.c -o fprint

 
$ ./fprint
This is a standard output info!
This is a standard error output info!

 

這是因爲默認情況下,shell所打開的stdout和stderr設備都是顯示屏幕。不過我們可以通過shell的重定向功能來將打印信息寫到文件中去。比如:

$ ./fprint >output.log

 
This is a standard error output info!
$ cat output.log
This is a standard output info!

 

這樣,我們把stdout的輸出寫到了文件output.log中,不過stderr的輸出還是在屏幕上。如何重定向stderr呢?這需要用到shell定義的文件描述符。在shell下stdin, stdout, 和stderr的文件描述符分別是0, 1和2,我們可以用下面的方法重定向:

$ ./fprint >output.log 2>error.log

 
$ cat output.log
This is a standard output info!
$ cat error.log
This is a standard error output info!
$
$ ./fprint >output.log 2>&1
$ cat output.log
This is a standard error output info!
This is a standard output info!

 

其中./fprint >output.log 2>error.log分別將stdout和stderr的輸出寫入到文件output.log和error.log中,而./fprint >output.log 2>&1則表示將stderr的輸出追加到stdout的文件output.log中(結果是output.log中既有stdout輸出也有stderr輸出)。
一些常用的shell I/O語法如下:
cmd > file  把 stdout 重定向到 file 文件中
cmd >> file  把 stdout 重定向到 file 文件中(追加)
cmd 1> fiel  把 stdout 重定向到 file 文件中
cmd > file 2>&1  把 stdout 和 stderr 一起重定向到 file 文件中
cmd 2> file  把 stderr 重定向到 file 文件中
cmd 2>> file  把 stderr 重定向到 file 文件中(追加)
cmd >> file 2>&1  把 stderr 和 stderr 一起重定向到 file 文件中(追加)
在平時的簡單調試中,我們可以靈活利用這些方法來快速得到log文件。
 
Ø       freopen()進行重定向
有時候我們要求在程序中能夠控制標準流的重定向,這時可以利用標準C庫函數freopen()。freopen()的函數原型如下:

FILE *freopen(const char *filename, const char *mode, FILE *stream)

 

 

 
下面的代碼用來測試用函數freopen()重定向stderr:

     1 #include <stdio.h>

 
     2
     3 int main()
     4 {
     5      if (freopen("err.log", "w", stderr)==NULL)
     6          fprintf(stderr, "error redirecting stderr\n");
     7      fprintf(stdout, "This is a standard output info!\n");
     8      fprintf(stderr, "This is a standard error output info!\n");
     9      fclose(stderr);
    10      return 0;
    11 }

 

在第5行我們用freopen()函數將stderr重定向到了”err.log”文件,這樣得到的結果如下:

$ gcc print_log.c -o print_log

 
$ ./print_log
This is a standard output info!
$ cat err.log
This is a standard error output info!

 

可見第8行打印到stderr的信息被重定向到了err.log文件中,而第7stdout的打印信息則還是輸出到了屏幕上
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章