默認打開pr_debug和dev_dbg

在進行Linux驅動開發時經常見到使用pr_debug和dev_dbg打印驅動的log,如果在內核配置時選擇了CONFIG_DYNAMIC_DEBUG宏,那麼就可以利用類似下面的命令打開對應文件的log:

echo -n "file xxx.c +p" > /sys/kernel/debug/dynamic_debug/control

但是有時候我們需要看到這個文件在內核啓動階段的log,那麼改怎麼辦呢?

這裏有兩種方法:

方法一 修改內核傳參

修改bootloader傳遞給kernel的bootargs,如果使用了設備樹的話,可以修改在chosen節點中bootargs屬性的值,具體方法內核文檔:Documentation/dynamic-debug-howto.txt

這種方案的優點是不需要修改驅動代碼。

方法二 在需要開啓log的驅動文件的開頭定義宏DEBUG

這樣該驅動文件中的pr_debug和dev_dbg就可以打開了。

比如驅動文件的名字是tfa98xx.c,那麼就在其第一個非註釋行添加DEBUG宏的定義:

/*
 * tfa98xx.c   tfa98xx codec module
 *
 * Copyright (c) 2015 NXP Semiconductors
 *
 *  Author: Sebastien Jan <[email protected]>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#define DEBUG
#define pr_fmt(fmt) "%s(): " fmt, __func__

#include <linux/module.h>
#include <linux/i2c.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <linux/of_gpio.h>
......

爲什麼這樣做可以實現呢?下面我們以pr_debug爲例簡單分析。

在內核配置了CONFIG_DYNAMIC_DEBUG後,pr_debug的定義如下:

#define pr_debug(fmt, ...) \
    dynamic_pr_debug(fmt, ##__VA_ARGS__)

dynamic_pr_debug的定義如下:

#define dynamic_pr_debug(fmt, ...)                do {                                    DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);            if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT))            __dynamic_pr_debug(&descriptor, pr_fmt(fmt),                       ##__VA_ARGS__);        } while (0)

這裏用到了宏DEFINE_DYNAMIC_DEBUG_METADATA,定義如下:

#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)            static struct _ddebug  __aligned(8)                __attribute__((section("__verbose"))) name = {                .modname = KBUILD_MODNAME,                    .function = __func__,                        .filename = __FILE__,                        .format = (fmt),                        .lineno = __LINE__,                        .flags =  _DPRINTK_FLAGS_DEFAULT,            }

__dynamic_pr_debug的定義如下:

void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
{
    va_list args;
    struct va_format vaf;
    char buf[PREFIX_SIZE];

    BUG_ON(!descriptor);
    BUG_ON(!fmt);

    va_start(args, fmt);

    vaf.fmt = fmt;
    vaf.va = &args;

    printk(KERN_DEBUG "%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf);

    va_end(args);
}

從上面的代碼可以看到,每一個pr_debug都對應一個名爲descriptor,類型爲struct _ddebug的變量,存放在kernel的__verbose段。決定這個pr_debug能否輸出log的條件就是descriptor.flags & _DPRINTK_FLAGS_PRINT爲true。

在定義descriptor時,將其flags成員賦值爲了_DPRINTK_FLAGS_DEFAULT,下面看一下這兩個宏的定義:

#if defined DEBUG
#define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
#else
#define _DPRINTK_FLAGS_DEFAULT 0
#endif

可以看到,如果定義了宏DEBUG,那麼_DPRINTK_FLAGS_DEFAULT其實就是_DPRINTK_FLAGS_PRINT,所以默認就是可以打印的。如果沒有定義,那麼_DPRINTK_FLAGS_DEFAULT就是0,上面的條件不會成立,也就打印不出來。

时间: 2024-11-03 05:26:28

默認打開pr_debug和dev_dbg的相关文章

pr_debug、dev_dbg等动态调试一

内核版本:Linux-3.14 pr_debug: #if defined(CONFIG_DYNAMIC_DEBUG) /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ #define pr_debug(fmt, ...) \ dynamic_pr_debug(fmt, ##__VA_ARGS__) #elif defined(DEBUG) #define pr_debug(fmt, ...) \

PHP中的常量默認是全局變量

define("LEO","歡迎來到PHP世界!"); function show(){ echo LEO; } show(); PHP中的常量默認是全局變量,可以在任何地方調用 define(name,value,true) 這個函數接收3個參數.最好一個參數表示是否區分大小寫(true不區分,false區分)

pr_debug、dev_dbg等动态调试二

内核版本:Linux-3.14 作者:彭东林 邮箱:[email protected] 下面我们简要分析 1: echo -n "file demo.c +p" > /sys/kernel/debug/dynamic_debug/control 的实现. 首先看一下dynamic_dedbg/control是如何生成的? 代码位置 lib/dynamic_debug.c 1: static int __init dynamic_debug_init_debugfs(void) 2

02.C#可空類型、默認參數、LINQ(一章1.3-1.4)

利用上班時間發個隨筆,不知領導會不會看到,可能會有同事看到也說不定啊:) 關于可空類型,在C#1中沒有這個概念,在C#3中引入的.那比如我們要實現一個表示人的類,人有名字和年齡兩個屬性,如何表示一個沒有年齡的人呢? 一般作法會將一人int類型封裝成一個引用類型,有人的類中使用成員屬性,該屬性的類型為剛封裝的引用類型,如下 1 public class Person 2 { 3 private string name; 4 private PersonAge age; 5 6 public Per

【Exchange 2019 設置技巧】修改默認附件大小

問,我如何修改附件默認大小的限制?(默認10MB) 答, 默認 修改 結果 原文地址:http://blog.51cto.com/happynews/2161554

【Exchange 2019 設置技巧】用戶郵箱默認配額設定

問,如何統一設置郵箱默認配額?答,由於我指定數據庫01,做配額設定,所以只是在數據庫01做修改. 結果 Exchange PoserSheet 查詢結果Get-Mailbox <Identity> | Format-List *Quota 由於是默認配額,所以ProhibitSendQuota : UnlimitedProhibitSendReceiveQuota : Unlimited當然你是可以自由設定用戶的具體數值. 原文地址:http://blog.51cto.com/happynew

開啟MacOS NTFS默認加載只讀改成讀寫

第一步:開啟終端進入root模式 $ sudo -s 第二步:備份NTFS初始文件 # mv /sbin/mount_ntfs /sbin/mount_ntfs_bak 第三步:新建需要掛載的NTFS腳本 # vim /sbin/mount_ntfs #!/bin/sh/sbin/mount_ntfs_orig -o rw,nobrowse "[email protected]" 第四步:設置掛載文件的權限 # chmod a+x /sbin/mount_ntfs 第五步:重啓Mac即

pr_debug、dev_dbg等动态调试三

内核版本:Linux-3.14 作者:彭东林 邮箱:[email protected] 如果没有使用CONFIG_DYNAMIC_DEBUG,那么就需要定义DEBUG,那么此时pr_debug就退化为了printk. 如果定义了CONFIG_DYNAMIC_DEBUG,下面有几种方法: 参考内核文档:Documentation/dynamic-debug-howto.txt Introduction ============ This document describes how to use

IOS開發之——objectForKey與valueForKey在NSDictionary中的差異

從 NSDictionary 取值的時候有兩個方法,objectForKey: 和 valueForKey:,這兩個方法具體有什麼不同呢? 先從 NSDictionary 文檔中來看這兩個方法的定義: objectForKey: returns the value associated with aKey, or nil if no value is associated with aKey. 返回指定 key 的 value,若沒有這個 key 返回 nil. valueForKey: ret