开始
前面说的话
printk 调试
int do_syslog(int type, char __user *buf, int len, int source) { bool clear = false; static int saved_console_loglevel = LOGLEVEL_DEFAULT; int error; error = check_syslog_permissions(type, source); if (error) return error; switch (type) { case SYSLOG_ACTION_CLOSE: /* Close log */ break; case SYSLOG_ACTION_OPEN: /* Open log */ break; case SYSLOG_ACTION_READ: /* Read from log */ if (!buf || len < 0) return -EINVAL; if (!len) return 0; if (!access_ok(buf, len)) return -EFAULT; error = wait_event_interruptible(log_wait, syslog_seq != log_next_seq); if (error) return error; error = syslog_print(buf, len); break; /* Read/clear last kernel messages */ case SYSLOG_ACTION_READ_CLEAR: clear = true; /* FALL THRU */ /* Read last kernel messages */ case SYSLOG_ACTION_READ_ALL: if (!buf || len < 0) return -EINVAL; if (!len) return 0; if (!access_ok(buf, len)) return -EFAULT; error = syslog_print_all(buf, len, clear); break; /* Clear ring buffer */ case SYSLOG_ACTION_CLEAR: syslog_clear(); break; /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_OFF: if (saved_console_loglevel == LOGLEVEL_DEFAULT) saved_console_loglevel = console_loglevel; console_loglevel = minimum_console_loglevel; break; /* Enable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: if (saved_console_loglevel != LOGLEVEL_DEFAULT) { console_loglevel = saved_console_loglevel; saved_console_loglevel = LOGLEVEL_DEFAULT; } break; /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: if (len < 1 || len > 8) return -EINVAL; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; /* Implicitly re-enable logging to console */ saved_console_loglevel = LOGLEVEL_DEFAULT; break; /* Number of chars in the log buffer */ case SYSLOG_ACTION_SIZE_UNREAD: logbuf_lock_irq(); if (syslog_seq < log_first_seq) { /* messages are gone, move to first one */ syslog_seq = log_first_seq; syslog_idx = log_first_idx; syslog_partial = 0; } if (source == SYSLOG_FROM_PROC) { /* * Short-cut for poll(/"proc/kmsg") which simply checks * for pending data, not the size; return the count of * records, not the length. */ error = log_next_seq - syslog_seq; } else { u64 seq = syslog_seq; u32 idx = syslog_idx; bool time = syslog_partial ? syslog_time : printk_time; while (seq < log_next_seq) { struct printk_log *msg = log_from_idx(idx); error += msg_print_text(msg, true, time, NULL, 0); time = printk_time; idx = log_next(idx); seq++; } error -= syslog_partial; } logbuf_unlock_irq(); break; /* Size of the log buffer */ case SYSLOG_ACTION_SIZE_BUFFER: error = log_buf_len; break; default: error = -EINVAL; break; } return error; } |
/** * printk - print a kernel message * @fmt: format string * * This is printk(). It can be called from any context. We want it to work. * * We try to grab the console_lock. If we succeed, it's easy - we log the output and * call the console drivers. If we fail to get the semaphore we place the output * into the log buffer and return. The current holder of the console_sem will * notice the new output in console_unlock(); and will send it to the * consoles before releasing the lock. * * One effect of this deferred printing is that code which calls printk() and * then changes console_loglevel may break. This is because console_loglevel * is inspected when the actual printing occurs. * * See also: * printf(3) * * See the vsnprintf() documentation for format string extensions over C99. */ asmlinkage int printk(const char *fmt, ...) { va_list args; int r; #ifdef CONFIG_KGDB_KDB if (unlikely(kdb_trap_printk)) { va_start(args, fmt); r = vkdb_printf(fmt, args); va_end(args); return r; } #endif va_start(args, fmt); r = vprintk(fmt, args); va_end(args); return r; } |
#define KERN_EMERG "<0>" /* system is unusable 系统不可用*/ #define KERN_ALERT "<1>" /* action must be taken immediately 需要立即采取行动*/ #define KERN_CRIT "<2>" /* critical conditions 严重情况*/ #define KERN_ERR "<3>" /* error conditions 错误情况*/ #define KERN_WARNING "<4>" /* warning conditions 警告情况*/ #define KERN_NOTICE "<5>" /* normal but significant condition 正常情况,但要注意*/ #define KERN_INFO "<6>" /* informational 信息型消息*/ #define KERN_DEBUG "<7>" /* debug-level messages 调试级别信息*/ /* Use the default kernel loglevel 默认内核日志级别*/ #define KERN_DEFAULT "<d>" /* * line that had no enclosing(封闭) \n). Only to be used by core/arch code * during early bootup (a continued line is not SMP-safe otherwise). #define KERN_CONT "<c>" |
/* * Call the console drivers, asking them to write out * log_buf[start] to log_buf[end - 1]. * The console_lock must be held. */ static void call_console_drivers(unsigned start, unsigned end) { unsigned cur_index, start_print; static int msg_level = -1; BUG_ON(((int)(start - end)) > 0); cur_index = start; start_print = start; while (cur_index != end) { if (msg_level < 0 && ((end - cur_index) > 2)) { /* * prepare buf_prefix, as a contiguous array, * to be processed by log_prefix function */ char buf_prefix[SYSLOG_PRI_MAX_LENGTH+1]; unsigned i; for (i = 0; i < ((end - cur_index)) && (i < SYSLOG_PRI_MAX_LENGTH); i++) { buf_prefix[i] = LOG_BUF(cur_index + i); } buf_prefix[i] = '\0'; /* force '\0' as last string character */ /* strip log prefix */
cur_index += log_prefix((const char *)&buf_prefix, &msg_level, NULL); start_print = cur_index; } while (cur_index != end) { char c = LOG_BUF(cur_index); cur_index++; if (c == '\n') { if (msg_level < 0) { /* * printk() has already given us loglevel tags in * the buffer. This code is here in case the * log buffer has wrapped right round and scribbled * on those tags */ msg_level = default_message_loglevel; } _call_console_drivers(start_print, cur_index, msg_level); msg_level = -1; start_print = cur_index; break; } } } _call_console_drivers(start_print, end, msg_level); |
用下面这个命令
root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# echo 7 > /proc/sys/kernel/printk root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# cat /proc/sys/kernel/printk 7 4 1 7 root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# echo 8 8 1 8 > /proc/sys/kernel/printk root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# cat /proc/sys/kernel/printk 8 8 1 8 root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# |
#ifndef pr_fmt #define pr_fmt(fmt) fmt #endif #define pr_emerg(fmt, ...) \ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) #define pr_alert(fmt, ...) \ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) #define pr_crit(fmt, ...) \ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) #define pr_err(fmt, ...) \ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) #define pr_warning(fmt, ...) \ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) #define pr_warn pr_warning #define pr_notice(fmt, ...) \ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) #define pr_info(fmt, ...) \ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) /* 除非定义了DEBUG ,否则pr_devel()不产生任何代码 */ #ifdef DEBUG #define pr_devel(fmt, ...) \ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #else #define pr_devel(fmt, ...) \ no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #endif /* 如果你在写一个驱动,请使用dev_dbg */ #if defined(DEBUG) #define pr_debug(fmt, ...) \ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #elif 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__) #else #define pr_debug(fmt, ...) \ no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #endif |
root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# dmesg |tail -1 [ 36.406262] init: vmware-tools pre-start process (1789) terminated with status 1 root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# dmesg |head -1 [ 0.000000] Initializing cgroup subsys cpuset root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# dmesg --help Usage: dmesg [options] Options: -C, --clear clear the kernel ring buffer -c, --read-clear read and clear all messages -D, --console-off disable printing messages to console -d, --show-delta show time delta between printed messages -E, --console-on enable printing messages to console -f, --facility <list> restrict output to defined facilities -h, --help display this help and exit -k, --kernel display kernel messages -l, --level <list> restrict output to defined levels -n, --console-level <level> set level of messages printed to console -r, --raw print the raw message buffer -s, --buffer-size <size> buffer size to query the kernel ring buffer -T, --ctime show human readable timestamp (could be inaccurate if you have used SUSPEND/RESUME) -t, --notime don't print messages timestamp -u, --userspace display userspace messages -V, --version output version information and exit -x, --decode decode facility and level to readable string Supported log facilities: kern - kernel messages user - random user-level messages mail - mail system daemon - system daemons auth - security/authorization messages syslog - messages generated internally by syslogd lpr - line printer subsystem news - network news subsystem Supported log levels (priorities): emerg - system is unusable alert - action must be taken immediately crit - critical conditions err - error conditions warn - warning conditions notice - normal but significant condition info - informational debug - debug-level messages root@ubuntu:/usr/src/linux-source-3.2.0/linux-source-3.2.0# |
动态打印内核日志
/* If you are writing a driver, please use dev_dbg instead */ #if defined(DEBUG) #define pr_debug(fmt, ...) \ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #elif 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__) #else #define pr_debug(fmt, ...) \ no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #endif |
#echo 'file sprdfb_main.c +p' > /sys/kernel/debug/dynamic_debug/control #echo 'file lcdc.c +p' > /sys/kernel/debug/dynamic_debug/control #echo 'file sprdfb_dispc.c +p' > /sys/kernel/debug/dynamic_debug/control #echo 'file sprd-core.c +p' > /sys/kernel/debug/dynamic_debug/control |
#echo 'file sprdfb_main.c -p' > /sys/kernel/debug/dynamic_debug/control #echo 'file lcdc.c -p' > /sys/kernel/debug/dynamic_debug/control #echo 'file sprd-corec.c -p' > /sys/kernel/debug/dynamic_debug/control |
cat /sys/kernel/debug/dynamic_debug/control |
linux@ubuntu:~$ sudo find / -iname dynamic_debug /sys/kernel/debug/dynamic_debug |
--- a/kernel/drivers/gosodrv/touchscreen/ft5x06_ts.c +++ b/kernel/drivers/gosodrv/touchscreen/ft5x06_ts.c @@ -402,6 +402,7 @@ static void ft5x0x_ts_pen_irq_work(struct work_struct *work) struct ft5x06_ts_data *data = container_of(work, struct ft5x06_ts_data, pen_event_work); //printk("ft5x0x_ts_pen_irq_work\n"); pr_debug("%s: dev_dbg test owen.wei ==============\n", __func__); ret = ft5x06_handle_touchdata(data); if (ret) pr_err("%s: handling touchdata failed\n", __func__); |
adb root 获取root权限 255|root@android:/ # mkdir data/debugfs 建立debugfs日志文件 mkdir data/debugfs root@android:/ # mount -t debugfs none /data/debugfs 挂载到这个日志文件里去 mount -t debugfs none /data/debugfs root@android:/ # echo -n "file ft5x06_ts.c +p" > /data/debugfs/dynamic_debug/control 打开ft5x06_ts.c下面的pr_debug日志输出 /data/debugfs/dynamic_debug/control < root@android:/ # |
标志规范包括随后的改变操作 由一个或多个标志字符组成。变更操作是一个 人物: - 删除给定的标志 + 添加给定的标志 = 将标志设置为给定的标志 标志是: p 启用 pr_debug()调用点。 f 在打印的消息中包含功能名称 l 在打印的消息中包含行号 m 在打印的消息中包含模块名称 t 在非中断上下文生成的消息中包含线程ID _没有设置标志。(或者“ 与其他输入D) |
Examples ======== // enable the message at line 1603 of file svcsock.c nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > <debugfs>/dynamic_debug/control 打开某个文件某一行的日志 // enable all the messages in file svcsock.c 打开某个文件的所有日志 nullarbor:~ # echo -n 'file svcsock.c +p' > <debugfs>/dynamic_debug/control // enable all the messages in the NFS server module 打开某个模块的所有日志 nullarbor:~ # echo -n 'module nfsd +p' > <debugfs>/dynamic_debug/control // enable all 12 messages in the function svc_process() 打开某个函数的所有日志 nullarbor:~ # echo -n 'func svc_process +p' > <debugfs>/dynamic_debug/control // disable all 12 messages in the function svc_process() 关闭某个文件的所有日志 nullarbor:~ # echo -n 'func svc_process -p' > <debugfs>/dynamic_debug/control // enable messages for NFS calls READ, READLINK, READDIR and READDIR+. nullarbor:~ # echo -n 'format "nfsd: READ" +p' > <debugfs>/dynamic_debug/control |
更改printk输出串口号
实战过程
总结