Maison  >  Article  >  Tutoriel système  >  Fonction de sortie de débogage dans le noyau Linux : explication détaillée de printk

Fonction de sortie de débogage dans le noyau Linux : explication détaillée de printk

PHPz
PHPzavant
2024-02-14 20:33:141239parcourir

printk est l'une des fonctions de débogage les plus couramment utilisées dans le noyau Linux. Elle est utilisée pour afficher des informations de débogage vers le tampon ou la console du noyau, telles que la valeur des variables, le flux d'exécution des fonctions, la cause des erreurs, etc. L’avantage de printk est qu’il est simple et facile à utiliser et ne nécessite aucun équipement ni pilote supplémentaire. L'implémentation de printk implique des concepts tels que les tampons du noyau, les niveaux de journalisation et les chaînes formatées. Dans cet article, nous présenterons les principes et méthodes de printk, une technologie de débogage du noyau Linux, et illustrerons leur utilisation et leurs précautions avec des exemples.

Fonction de sortie de débogage dans le noyau Linux : explication détaillée de printk

1. Introduction (basé sur Linux s3c2440)

Parmi les technologies de débogage du noyau, la plus simple est l'utilisation de printk. Son utilisation est similaire à l'utilisation de printf dans les applications en langage C. Dans l'application, elle s'appuie sur la bibliothèque de stdio.h, tandis que dans le noyau Linux, elle existe. il n'existe pas de bibliothèque de ce type, donc dans le noyau Linux, l'utilisation de ce printk nécessite une certaine compréhension de l'implémentation du noyau.

La différence entre printf et printk : printk ajoutera des caractères de style "" au début. La plage de N est de 0 à 7, indiquant le niveau de cette information.

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

Initialisez le niveau console_loglevel à 7 dans le fichier noyau Printk.c (kernel).

/* 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. Vérifiez la configuration du niveau via la commande cat /proc/sys/kernel/printk :

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

7 4 1 7 parmi eux correspondent à : console_loglevel, default_message_loglevel, minimum_console_loglevel, default_console_loglevel

3. Modifier la configuration du niveau :

#echo « 1 4 1 7 »>/proc/sys/kernel/printk Modifiez ces quatre valeurs Lorsque console_loglevel est défini sur 1, toutes les informations de débogage seront imprimées.

4. Le nom et l'utilisation de l'enregistrement de la fonction printk

Dans le fichier noyau : Kernel.h (includelinux), 8 niveaux de noms de 0 à 7 sont définis

#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])

Utilisez printk :

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

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

Dans ① et ②, nous devons visualiser les données dans le tampon log_buf pour voir les informations imprimées. Besoin d'utiliser la commande #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)................................

Vous pouvez également utiliser cat /proc/kmsg& pour exécuter en arrière-plan et imprimer les informations de débogage en temps réel. En ②, __FILE__, FUNCTION et __LINE__ correspondent respectivement à ce fichier, à cette fonction et à quelle ligne. Très pratique.

# 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. La relation entre le port série et la fonction printk :

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);
}

La fonction de sortie du port série appellera la fonction s3c24xx_serial_console_putchar

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 //串口设置函数
}; 

Cette fonction est liée au matériel. Elle lit le registre pour voir si les données ont été envoyées. Enfin, les données sont écrites dans le registre octet par octet. Le contrôleur de port série s3c2440 enverra automatiquement les données.

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);
}

Console de uboot=ttySAC0, s'il est reconnu comme port série 0 sous Linux, il y a le code suivant dans /kernel/printk.c,

__setup("console=", console_setup);

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

Lorsque le noyau commence à s'exécuter, lorsque le paramètre de ligne de commande "console=..." est trouvé, la fonction console_setup sera appelée pour l'analyse des données. Pour le paramètre de ligne de commande "console=ttySAC0", il sera analysé : le. le nom de l'appareil (nom) est ttySAC, l'index est 0 et ces informations sont stockées dans un tableau global de type console_cmdline et de nom console_cmdline (remarque : le nom du tableau et le type du tableau sont les mêmes)

Dans le registre_console(&s3c24xx_serial_console) suivant ;, la structure s3c24xx_serial_console sera comparée aux périphériques du tableau console_cmdline.

①Le nom analysé est S3C24XX_SERIAL_NAME, qui est "ttySAC", et le nom dans la commande dans console_cmdline est également "ttySAC"

②L'index dans la structure s3c24xx_serial_console est -1, ce qui signifie utiliser l'index dans le paramètre de ligne de commande "console=ttySAC0", index = 0

Grâce à cet article, nous avons découvert les principes et les méthodes de printk, une technologie de débogage du noyau Linux, qui peut être utilisée pour déboguer et afficher le noyau. Nous devons choisir la méthode appropriée en fonction des besoins réels et suivre certains principes de base, tels que l'utilisation du bon niveau de journalisation, l'utilisation de la bonne chaîne de format, l'utilisation de la bonne fonction de sortie, etc. Printk est l'une des fonctions de débogage les plus simples et les plus efficaces du noyau Linux. Elle peut réaliser des commentaires et une surveillance du noyau, et peut également améliorer la maintenabilité et l'évolutivité du noyau. J’espère que cet article pourra vous être utile et inspirant.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer