在嵌入式開發(fā)中,我們都是使用串口進(jìn)行調(diào)試定位問題。然而在成品調(diào)試或者遠(yuǎn)程調(diào)試時,沒有串口,只能telnet進(jìn)去,少了很多應(yīng)用進(jìn)程的打印,這樣就不利于我們發(fā)現(xiàn)問題。需要一種方法把串口所有輸出重定向到telnet。
這就涉及到一些終端概念,可以參考上篇博文linux下tty, ttyn, pts, pty, ttySn, console理解。主要是利用tty的ioctl重定向方法來實現(xiàn)重定向,下面直接貼代碼:
/************************************************************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************************************************************//* 內(nèi)核的打印不能重定向過來,應(yīng)用層打印可以重定向打印過來 查看內(nèi)核的打印,cat /PRoc/kmsg,在輸出完緩沖區(qū)內(nèi)容后,會阻塞卡住,內(nèi)核有新的輸出時會繼續(xù)輸出。 如果要把內(nèi)核打印到telnet,那么需要修改printk.c。 kernel和user空間下都有一個console,關(guān)系到kernel下printk的方向和user下printf的方向,實現(xiàn)差別很大。 kernel下的console是輸入輸出設(shè)備driver中實現(xiàn)的簡單的輸出console,只實現(xiàn)write函數(shù),并且是直接輸出到設(shè)備。 user空間下的console,實際就是tty的一個特殊實現(xiàn),大多數(shù)操作函數(shù)都繼承tty,所以對于console的讀寫,都是由kernel的tty層來最終發(fā)送到設(shè)備。*/#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; } /* 獲取當(dāng)前tty名稱 */ tty_name = ttyname(STDOUT_FILENO); printf("tty_name: %s/n", tty_name); if(!strcmp(argv[1], "on")) { /* 重定向console到當(dāng)前tty */ tty = open(tty_name, O_RDONLY | O_WRONLY); ioctl(tty, TIOCCONS); perror("ioctl TIOCCONS"); } else if(!strcmp(argv[1], "off")) { /* 恢復(fù)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進(jìn)板子,然后telnet進(jìn)去,用on參數(shù)執(zhí)行這個程序就好了
內(nèi)核打印到telnet的思考內(nèi)核的打印沒有走tty的中間層,直接在printk哪兒調(diào)用了注冊設(shè)備的write方法。如果要把printk打印到telnet,那么就需要分析下printk實現(xiàn)代碼。自己改了下在printk輸出時把數(shù)據(jù)重新寫到/dev/console的這種方法,因為對printk邏輯不清楚,鎖處理會產(chǎn)生問題,造成死鎖或者系統(tǒng)掛掉。
新聞熱點
疑難解答