日常現象
在調試嵌入式裝置的時候需要接序列槽,通過序列槽将列印輸出到顯示終端。但是很多時候接序列槽是裝置是一件很麻煩的事情,比如,序列槽闆,序列槽線等。
分析
核心的列印不能重定向過來,但是應用層列印可以重定向列印過來檢視核心的列印,
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 <unistd.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#define FILE_PATH 512
int main(int argc, char * argv[])
{
int tty = -1;
int fd = -1;
char * tty_name = NULL;
if (argc < 2)
{
¦ printf("miss argv \n");
¦ return -1;
}
/* 擷取目前tty名稱 */
tty_name = ttyname(STDOUT_FILENO);
if (!tty_name)
{
¦ printf(" get error tty_name \n");
¦ return -1;
}
printf("get ok tty_name: %s \n", tty_name);
struct timeval lt;
gettimeofday(<, NULL);
char fname[FILE_PATH];
memset(fname, 0, FILE_PATH);
snprintf(fname, FILE_PATH, "/media/tty_%u.log", (unsigned int)lt.tv_usec);
if (!strcmp(argv[1], "on"))
{
¦ /* 重定向console到目前tty */
¦ tty = open(tty_name, O_RDONLY | O_WRONLY);
¦ ioctl(tty, TIOCCONS);
// 寫到檔案/media/tty_%u.log中
¦ //fd = open(fname, O_RDWR|O_CREAT|O_APPEND, 0777);
¦ //ioctl(fd, 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 -1;
}
//close(fd);
close(tty);
return 0;
}
根據以上代碼注釋可以有兩種選擇,第一将其重定向到終端顯示,第二将其重定向到.log檔案中參考 https://github.com/xbalabala/ttyrpld
mips-linux-uclibc-gnu-gcc -g console.c -o ./sharenfs/console.out