天天看點

序列槽輸出重定向

日常現象

在調試嵌入式裝置的時候需要接序列槽,通過序列槽将列印輸出到顯示終端。但是很多時候接序列槽是裝置是一件很麻煩的事情,比如,序列槽闆,序列槽線等。

分析

核心的列印不能重定向過來,但是應用層列印可以重定向列印過來檢視核心的列印,

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