Home >System Tutorial >LINUX >Debug output function in Linux kernel: detailed explanation of printk

Debug output function in Linux kernel: detailed explanation of printk

PHPz
PHPzforward
2024-02-14 20:33:141328browse

printk is one of the most commonly used debugging functions in the Linux kernel. It is used to output debugging information to the kernel buffer or console, such as the value of variables, the execution flow of functions, the cause of errors, etc. The advantage of printk is that it is simple and easy to use and does not require additional equipment or drivers. The implementation of printk involves concepts such as kernel buffer, log level, format string, etc. In this article, we will introduce the principles and methods of printk, a Linux kernel debugging technology, and illustrate their use and precautions with examples.

Debug output function in Linux kernel: detailed explanation of printk

1. Introduction (based on s3c2440 linux)

Among the kernel debugging technologies, the simplest is the use of printk. Its usage is similar to the use of printf in C language applications. The application relies on the library in stdio.h, while in linux There is no such library in the kernel, so in the Linux kernel, using this printk requires a certain understanding of the kernel's implementation.

The difference between printf and printk: printk will add "" style characters at the beginning. The range of N is 0~7, indicating the level of this information.

When n in printk(""......);

Initialize the console_loglevel level in the kernel file Printk.c (kernel) to 7.

/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */

/* We show everything that is MORE important than this.. */
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG
 */int console_printk[4] = {
    DEFAULT_CONSOLE_LOGLEVEL,    /* console_loglevel */
    DEFAULT_MESSAGE_LOGLEVEL,    /* default_message_loglevel */
    MINIMUM_CONSOLE_LOGLEVEL,    /* minimum_console_loglevel */
    DEFAULT_CONSOLE_LOGLEVEL,    /* default_console_loglevel */
};

2. Check the level configuration through the command cat /proc/sys/kernel/printk:

# cat /proc/sys/kernel/printk
7 4 1 7

7 4 1 7 among them correspond to: console_loglevel, default_message_loglevel, minimum_console_loglevel, default_console_loglevel

3. Modify the level configuration:

#echo “1 4 1 7”>/proc/sys/kernel/printk Change these four values. When console_loglevel is set to 1, all debugging information will be printed.

4. The name and usage of printk function records

In the kernel file: Kernel.h (include\linux) defines the names of 8 levels from 0 to 7

#define   KERN_EMERG   ""    /* system is unusable */
#define    KERN_ALERT    ""  
  /* action must be taken immediately */
#define    KERN_CRIT     ""    /* critical
 conditions */
#define    KERN_ERR      ""    /* error conditions */
#define   
 KERN_WARNING  ""    /* warning conditions */
#define    KERN_NOTICE   ""  
  /* normal but significant condition*/
#define    KERN_INFO     ""   
 /* informational*/
#define    KERN_DEBUG    ""    /* debug-level messages 
*/
#define console_loglevel      (console_printk[0])
#define 
default_message_loglevel (console_printk[1])
#define minimum_console_loglevel 
(console_printk[2])
#define default_console_loglevel (console_printk[3])

Use printk:

① printk(KERN_WARNING"there is a warning here!\n");//注意,中间没有逗号间隔。

② printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

In ① and ②, we need to check the data in the buffer log_buf to see the printed information. You need to use the command #dmesg

#``# dmesg``Linux version 2.6.22.6 (book@book-desktop) (gcc version 3.4.5) #19 Thu
 Dec 8 14:06:03 CST 2016``CPU: ARM920T
 [41129200] revision 0 (ARMv4T), cr=c0007177``Machine: SMDK2440``Memory policy: 
ECC disabled, Data cache writeback``On node 0 totalpages: 16384`` ``DMA zone: 128 
pages used ``for` `memmap`` ``DMA zone: 0 pages reserved`` ``DMA zone: 16256 pages,
 LIFO batch:3`` ``Normal zone: 0 pages used ``for` `memmap``CPU S3C2440A (id 0x32440001)................................

You can also use cat /proc/kmsg& to run in the background and print out debugging information in real time. In ②, __FILE__, FUNCTION, and __LINE__ respectively correspond to that file, that function, and which line. Very practical.

# cat /proc/kmsg&``# ./firstdrvtest on``/work/LinuxDrives/20.printk_debug/first_drv.c
 first_drv_open 23``/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 25``
/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 27``# ./firstdrvtest off`
`/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23``/work/LinuxDrives/
20.printk_debug/first_drv.c first_drv_open 25``/work/LinuxDrives/20.printk_debug
/first_drv.c first_drv_open 27

5. The relationship between the serial port and the printk function:

printk
    vprintk
        vscnprintf //先把输出信息放入临时BUFFER
                // Copy the output into log_buf.
                // 把临时BUFFER里的数据稍作处理,再写入log_buf
                // 比如printk("abc")会得到"abc", 再写入log_buf
                // 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息

        // 调用硬件的write函数输出
        release_console_sem    
            call_console_drivers
          //从log_buf得到数据,算出打印级别
                _call_console_drivers
                    if ((msg_log_level write //con是console_drivers链表中的项,对用具体的输出函

数 在drives/serial/s3c2410.c中查看

在该函数中注册一个console结构体
static void s3c24xx_serial_console_write(struct console *co, const char *s,
unsigned int count)
{
uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
}

The serial port output function will call the s3c24xx_serial_console_putchar function

static int s3c24xx_serial_initconsole(void)
{
    ...........................
    register_console(&s3c24xx_serial_console);
    return 0;
}
static struct console s3c24xx_serial_console =
{
.name = S3C24XX_SERIAL_NAME,//这个宏被定义为:TTYSAC
.device = uart_console_device, //init进程,用户程序打开/dev/console的时候会调用
.flags = CON_PRINTBUFFER,//打印还没有初始化化console前保存在log_buf里面的数据
.index = -1,//选择那个串口,由uboot中的命令决定
.write = s3c24xx_serial_console_write,//控制台输出函数
.setup = s3c24xx_serial_console_setup //串口设置函数
}; 

This function is related to hardware. Read the register to see if the data has been sent. Finally, write the data into the register byte by byte. The s3c2440 serial port controller will automatically send the data.

static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch)

{
unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
while (!s3c24xx_serial_console_txrdy(port, ufcon))
barrier();
wr_regb(cons_uart, S3C2410_UTXH, ch);
}

If console=ttySAC0 of uboot is recognized as serial port 0 in Linux, there is the following code in /kernel/printk.c,

__setup("console=", console_setup);

static int __init console_setup(char *str)
{
........
  add_preferred_console(name, idx, options);
} 

When the kernel starts executing, when the command line parameter "console=..." is found, the console_setup function will be called for data analysis. For the command line parameter "console=ttySAC0", the device name (name) will be parsed as ttySAC, index index is 0, this information is stored in a global array with type console_cmdline and name console_cmdline (note: the array name is the same as the array type)

In the subsequent register_console(&s3c24xx_serial_console);, the s3c24xx_serial_console structure will be compared with the devices in the console_cmdline array.

①The parsed name is S3C24XX_SERIAL_NAME, which is "ttySAC", and the name in the command in console_cmdline is also "ttySAC"

②The index index in the s3c24xx_serial_console structure is -1, which means using the index in the command line parameter "console=ttySAC0", index = 0

Из этой статьи мы узнали о принципах и методах printk, технологии отладки ядра Linux, которую можно использовать для отладки и вывода ядра. Мы должны выбрать подходящий метод, исходя из реальных потребностей, и следовать некоторым основным принципам, таким как использование правильного уровня журнала, использование правильной строки формата, использование правильной функции вывода и т. д. Printk — одна из самых простых и эффективных функций отладки в ядре Linux. Она может реализовать обратную связь и мониторинг ядра, а также улучшить удобство обслуживания и масштабируемость ядра. Я надеюсь, что эта статья может быть для вас полезной и вдохновляющей.

The above is the detailed content of Debug output function in Linux kernel: detailed explanation of printk. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:lxlinux.net. If there is any infringement, please contact admin@php.cn delete