Quietly enter the Linux kernel debugging (i)
This article base address: Http://blog.csdn.net/cugxueyu/archive/2007/12/21/1957740.aspx※Debugging work hardis a significant feature of kernel-level development, which differs from user-level development. ※Manage kernel debuggingAbility, largely depends on experience and on the entire operating system's grasp.I. Preparation before commissioningKernel-level bugs havebehavior is unreliable,definition not clearOr a number of specific, difficult to reproduce for kernel-level bug tracking and debugging. ※ for some definitions are not clear bugs, the key to the problem is to findBugsthe source, most of the time, when you reproduce a bug accurately, you are not far from success.second, in the kernel ofBugsFrom the error hidden in the source code to the bug shown in front of the witness, the attack is often a series of chain-reaction events that may start. Although the kernel debugging has some difficulties, but through your efforts and understanding, perhaps you will like thisChallenge。Third,PRINTK ()The formatted print function provided by the kernel. 1, the robustness of the PRINTK function is one of the most easily accepted characteristics of PRINTK, almost anywhere, at any time the kernel can call it (interrupt context, process context, hold lock, multiprocessor processing, etc.). ※ in the process of system start-up,before terminal initialization, which cannot be invoked in some places. 2, Record level PRINTK function can specify a record level, the kernel based on this level to determine whether to print messages on the terminal. Record level definition in <linux/kernel.h>: #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 */ Invocation mode: PRINTK (ker_debug "This is a DEBUG notice!/n"); The kernel uses this specified record level to console_loglevel the current terminal's record level to determine whether to print to the terminal. About < linux/kernel.h > console_loglevel definition: #define CONSOLE_LOGLEVEL (Console_printk[0]) <printk.c> definition: 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 * }; 3, record buffers kernel messages are saved in a log_buf_len-size ring queue。 about Log_buf_len definition: #define __log_buf_len (1 << config_log_buf_ SHIFT) ※ variable config_log_buf_shift is defined by the configuration file at kernel compile time, for the i386 platform, the value is defined as follows (in Linux26/arch/i386/defconfig): CONFIG_LOG_BUF_SHIFT=18 Record buffer Operations: ①, messages are read out to user space, this message is removed from the ring queue. ②, when the message buffer is full, the new message overwrites the old message in the queue if there is another PRINTK () call. ③, when reading and writing ring queues, synchronization problems can be easily resolved. ※ This record buffer is called a ring because its reading and writing are operated in the form of an annular queue. 4, SYSLOGD and KLOGD on standard Linux systems, user-space daemon KLOGD obtains kernel messages from the record buffer and saves them in the system log file through the syslogd daemon. KLOGD processes can read these messages either from the/proc/kmsg file or through the syslog () system call. By default, it selects the Read/proc method for implementation. The Klogd daemon is blocked until there is a new message in the message buffer. Once a new kernel message is available, the KLOGD is awakened, and the kernel message is read and processed. By default, the processing routine is to pass the kernel message to the SYSLOGD daemon. The SYSLOGD daemon typically writes incoming messages to the/var/log/messages file. However, you can configure it by/etc/syslog.conf files, and you can select other output files. Figure 1 X-rays of this process:Four,OOPSOOPS (also known as Panic) messages contain details of the system error, such as the contents of the CPU registers. Is the most common way the kernel informs users of the unfortunate occurrence. The kernel can only publish Oops, which includes outputting error messages to the terminals, outputting the information stored in the registers, and outputting traceable clues that can be traced. Typically, the kernel is in an unstable state after the oops is sent. There are a number of possible causes for Oops, including memory access that is out of bounds or illegal directives. ※ as a kernel developer, the Oops will always be processed. The important information contained in the ※oops is exactly the same for all architecture machines:register context and backtracking clues (Backtracking clues show the chain of function calls that caused the error to occur)。 1. Ksymoops in Linux, the traditional way to debug system crashes is to analyze Oops messages that are sent to the system console when a crash occurs. Once you have mastered the details, you can send the message to the Ksymoops utility, which will attempt to convert the code to a directive and map the stack value to the kernel symbol. ※ such as: The address in the backtracking clues, will be transformed by Ksymoops into the name visible function name. Figure 2 X-ray formatted Oops message process: Ksymoops requires a few things: Oops message output, System.map files from the running kernel, and/proc/ksyms, Vmlinux, and/proc/modules. For information on how to use Ksymoops, the kernel source code/usr/src/linux/documentation/oops-tracing.txt or the Ksymoops man page has a complete description to refer to. The Ksymoops Disassembly Code section, indicating the instruction where the error occurred, and displaying a trace section indicating how the code was invoked. 2. The kallsyms development version 2.5 kernel introduces the kallsyms feature, which can be enabled by defining config_kallsyms compilation options. This option to loadThe symbolic name of the memory address for the kernel mirror(that is, the function name), so the kernel can print the trace trail after decoding. Accordingly, the decoding oops also no longer need system.map and ksymoops tools. In addition, doing so will make the kernel larger, because the address counterpart symbol name must always reside on the kernel's memory. #cat/proc/kallsyms c0100240 t _stext c0100240 t run_init_process c0100240 t Stext c0100269 T Init ...Five, kernel Debug configuration optionsWhen compiling the kernel, the kernel provides a number of configuration options to facilitate debugging and testing of the code. ※ enabling options such as: Slab layer Debugging (Slab layer Debug option), High-memory Debugging (High-end memory debugging options), I/O mapping Debugging (I/O mapping debugging Options), Spin-lock D Ebugging (Spin lock debugging option), Stack-overflow checking (Stack overflow check option) and sleep-inside-spinlock checking (Spin lock sleep option). 1, debugging atomic operation from the core 2.5 development, in order tocheck all kinds of problems caused by atomic operation, the kernel provides an excellent tool. The kernel provides aAtomic Operation Counter, it can be configured to print warning messages and provide tracking clues once in the process of atomic operation, entering the city into sleep or doing some sleep-causing operations. So, including inusing Locks, a variety of potential bugs can be detected by calling schedule () when using a lock to request allocating memory in blocking mode. The following options maximize the use of this feature: Config_preempt = y Config_debug_kernel = y config_kllsyms = y Config_spinlock_sleep = ysix, triggeringBugsand print the information1. Some kernel calls can be used to easily mark Bugs, provide assertions and output information. The two most commonly used are bugs () and bug_on (). Defined in <include/asm-generic>:
#ifndef Have_arch_bug
#define BUG () do {
PRINTK ("Bug:failure at%s:%d/%s ()!", __file__, __line__, __function__);
Panic ("bug!"); /* Raise more serious error, not only print error message, and the whole system industry will suspend * *
} while (0)
#endif
#ifndef have_arch_bug_on
#define BUG_ON (condition) do {if (unlikely (condition)) BUG (), while (0)
#endif when these two macros are invoked, they cause oops.causes the stack's backtracking and error messages to print。 ※ These two calls can be used as assertions, such as: bug_on (bad_thing); 2, Dump_stack () Sometimes, only need to print the stack on the terminalBacktracking InformationTo help you debug. You can use Dump_stack () at this time. This function prints only the trace thread of the register context and function on the terminal. if (!debug_check) { PRINTK (kern_debug) provide some information.../n "); Dump_stack (); } Notes: Most of the content is from Linux kernel design and implementation-2nd edition