在嵌入式開發中,我們都是使用串口進行調試定位問題。然而在成品調試或者遠程調試時,沒有串口,只能telnet進去,少了很多應用進程的打印,這樣就不利于我們發現問題。需要一種方法把串口所有輸出重定向到telnet。
這就涉及到一些終端概念,可以參考上篇博文linux下tty, ttyn, pts, pty, ttySn, console理解。主要是利用tty的ioctl重定向方法來實現重定向,下面直接貼代碼:
/************************************************************Copyright (C), 2017, Leon, All Rights Reserved.FileName: console_redirect.cDescription: console輸出重定向Author: LeonVersion: 1.0Date: 2017-2-6 15:33:12Function:History:<author> <time> <version> <description> Leon************************************************************//* 內核的打印不能重定向過來,應用層打印可以重定向打印過來 查看內核的打印,cat /PRoc/kmsg,在輸出完緩沖區內容后,會阻塞卡住,內核有新的輸出時會繼續輸出。 如果要把內核打印到telnet,那么需要修改printk.c。 kernel和user空間下都有一個console,關系到kernel下printk的方向和user下printf的方向,實現差別很大。 kernel下的console是輸入輸出設備driver中實現的簡單的輸出console,只實現write函數,并且是直接輸出到設備。 user空間下的console,實際就是tty的一個特殊實現,大多數操作函數都繼承tty,所以對于console的讀寫,都是由kernel的tty層來最終發送到設備。*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/ioctl.h>#include <unistd.h>int main(int argc, char *argv[]){ int tty = -1; char *tty_name = NULL; if(argc < 2) { printf("miss argument/n"); return 0; } /* 獲取當前tty名稱 */ tty_name = ttyname(STDOUT_FILENO); printf("tty_name: %s/n", tty_name); if(!strcmp(argv[1], "on")) { /* 重定向console到當前tty */ tty = open(tty_name, O_RDONLY | O_WRONLY); ioctl(tty, TIOCCONS); perror("ioctl TIOCCONS"); } else if(!strcmp(argv[1], "off")) { /* 恢復console */ tty = open("/dev/console", O_RDONLY | O_WRONLY); ioctl(tty, TIOCCONS); perror("ioctl TIOCCONS"); } else { printf("error argument/n"); return 0; } close(tty); return 0;}使用交叉編譯tftp進板子,然后telnet進去,用on參數執行這個程序就好了
內核打印到telnet的思考內核的打印沒有走tty的中間層,直接在printk哪兒調用了注冊設備的write方法。如果要把printk打印到telnet,那么就需要分析下printk實現代碼。自己改了下在printk輸出時把數據重新寫到/dev/console的這種方法,因為對printk邏輯不清楚,鎖處理會產生問題,造成死鎖或者系統掛掉。
新聞熱點
疑難解答