printf重定向


用到第三方庫使用printf打印調試信息的時候往往需要重定向日志到文件, 但如果沒有源碼或修改點較多時就比較麻煩. 這里提供兩個重定位方法:
1. 修改值為1的文件描述符
默認printf打印指向標准輸出stdout(fd=1), 最終指向終端. 因此可以關閉值為1的文件描述符再打開另一文件, 之后printf打印就被寫入該文件中. 注意這種方法必須保證關閉fd與打開文件之間不會有其它文件操作(內核分配fd是順序分配的, 如有第三個文件打開則第三個文件的fd被設為1), 且fork進程會保留對應的fd, 即新進程也會操作同一文件, 需要做好互斥(可以通過關閉子進程fd來解決這個問題).
2. 修改printf實現
定義同名同類型的printf並修改其實現. 這里要注意一點, 默認打印不帶參數的字符串時gcc會將printf優化為puts, 解決辦法有兩個: 一是同樣重定義puts, 二是編譯時添加-fno-builtin-printf.

 1 #include <string.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <stdarg.h>
 6 #define REDIRECT
 7 #undef REDIRECT
 8 #ifdef REDIRECT
 9 int fd = -1;
10 #else
11 FILE *fp = NULL;
12 int printf(const char *fmt, ...)
13 {
14     va_list args;
15     int ret = 0;
16     va_start(args, fmt);
17     ret = vfprintf(fp, fmt, args);
18     va_end(args);
19     fflush(fp);
20     return ret;
21 }
22 /*
23 int puts(const char *s)
24 {
25     //add \n here to avoid buffering
26     return printf("%s\n", s);
27 }
28 */
29 #endif
30 int main()
31 {
32 #ifdef REDIRECT
33     close(1);
34     
35     fd = open("./out", O_RDWR | O_CREAT, 0755);
36     if (1 != fd)
37     {
38         fprintf(stderr, "open file fail with %d\n", fd);
39         return -1;
40     }
41     printf("this line shall written into file!\n");
42     //flush cache, man stdout for detail
43     fsync(fd);
44 #else
45     fp = fopen("./out", "w+");
46     if (NULL == fp)
47     {
48         fprintf(stderr, "open file fail\n");
49         return -1;
50     }
51     const char cmd[] = "this line shall written into file!\n";
52     printf("this line shall written into file!\n");
53     printf("this line shall written into file! more args %p\n", fp);
54 #endif
55     return 0;
56 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM