日常现象
在调试嵌入式设备的时候需要接串口,通过串口将打印输出到显示终端。但是很多时候接串口是设备是一件很麻烦的事情,比如,串口板,串口线等。
分析
内核的打印不能重定向过来,但是应用层打印可以重定向打印过来查看内核的打印,
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
说明
mips-linux-uclibc-gnu-gcc 是交叉编译工具,编译之后跑在君正平台。