Today, I will go to Chapter 4 debugging technology of Linux Driver (version 3rd.
I. kernel debugging support
We have already suggested that you learn how to write a driver to build and install your own kernel (Standard main kernel ). One of the most important reasons is that kernel developers have already set up a number of debugging functions. However, as these functions cause additional output and decrease, the release vendors usually disable the debugging functions in the release kernel.
To implement kernel debugging, I have added several kernel configurations:
Kernel hacking --->
Magic sysrq key
Kernel debugging
Debug Slab Memory allocations
Spinlock and RW-lock debugging: basic checks
Spinlock debugging: Sleep-inside-spinlock checking
Compile the kernel with debug info
Magic sysrq key
Device Drivers --->
Generic Driver options --->
Driver core verbose debug messages
General setup --->
Configure standard kernel features (for small systems) --->
Load all symbols for debugging/ksymoops
There are other configurations introduced in the book. Some of them are not needed, or they are not supported by S3C2440, and cannot be seen in the menu.
Ii. Print and debug
(1) printk
First, printk has eight loglevels, which are defined in:
# 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 */
The default level of unspecified priority is defined in/kernel/printk. C:
# Define default_message_loglevel 4/* kern_warning */
Information can be displayed only when the priority value is smaller than the value of the integer variable lele_loglevel. The initial value of console_loglevel default_console_loglevel is also defined in/kernel/printk. C:
# Define default_console_loglevel 7/* anything more serious than kern_debug */
While the program that changes the console_loglevel is running (provided in Linux Device Driver (version 3rd) as follows:
# Include stdio. h>
# Include stdlib. h>
# Include string. h>
# Include errno. h>
# DEFINE _ Library _/* _ syscall3 and friends are only available through this */
# Include Linux/unistd. h>
/* Define the system call, to override the library function */
_ Syscall3 (INT, syslog, Int, type, char *, bufp, Int, Len );
Int main (INT argc, char ** argv)
{
Int level;
If (argc = 2 ){
Level = atoi (argv [1]);/* The chosen console */
} Else {
Fprintf (stderr, "% s: Need a single Arg \ n", argv [0]); exit (1 );
}
If (syslog (8, null, level) 0 ){
Fprintf (stderr, "% s: syslog (setlevel): % s \ n ",
Argv [0], strerror (errno ));
Exit (1 );
}
Exit (0 );
}
I don't understand the most critical "syslog (8, null, level)" statement. I didn't find the relevant information. However, the experiment on the arm9-board shows that the program is OK! I used the hello World module for an experiment. The phenomenon is the same as that in the book.
[Tekkaman2440 @ sbc2440v4] # cd/tmp/
[Tekkaman2440 @ sbc2440v4] #./setlevel 1
[Tekkaman2440 @ sbc2440v4] # cd/lib/modules/
[Tekkaman2440 @ sbc2440v4] # insmod hello. Ko
[Tekkaman2440 @ sbc2440v4] # rmmod hello
[Tekkaman2440 @ sbc2440v4] # cd/tmp/
[Tekkaman2440 @ sbc2440v4] #./setlevel 7
[Tekkaman2440 @ sbc2440v4] # cd/lib/modules/
[Tekkaman2440 @ sbc2440v4] # insmod hello. Ko
Hello, tekkaman ninja!
[Tekkaman2440 @ sbc2440v4] # rmmod hello
Goodbye, tekkaman ninja!
Love Linux! Love arm! Love Keke!
[Tekkaman2440 @ sbc2440v4] #
You can also change the console_loglevel value by accessing/proc/sys/kernel/printk:
[Tekkaman2440 @ sbc2440v4] # Echo 1>/proc/sys/kernel/printk
[Tekkaman2440 @ sbc2440v4] # Cat/proc/sys/kernel/printk
1 4 1 7
[Tekkaman2440 @ sbc2440v4] # insmod hello. Ko
[Tekkaman2440 @ sbc2440v4] # rmmod hello
[Tekkaman2440 @ sbc2440v4] # Echo 7>/proc/sys/kernel/printk
[Tekkaman2440 @ sbc2440v4] # Cat/proc/sys/kernel/printk7 4 1 7
[Tekkaman2440 @ sbc2440v4] # insmod hello. Ko
Hello, tekkaman ninja!
[Tekkaman2440 @ sbc2440v4] # rmmod hello
Goodbye, tekkaman ninja!
Love Linux! Love arm! Love Keke!
Meanings of the four numbers: Current loglevel, default loglevel, minimum allowed loglevel, and default loglevel during boot.
To enable and disable debugging information conveniently, the Linux Device Driver (version 3rd) provides the following source code:
/* Macros to help debugging */
# UNDEF pdebug/* UNDEF it, just in case */
# Ifdef scull_debug
# Ifdef _ KERNEL __
/* This one if debugging is on, and kernel space */
# Define pdebug (FMT, argS...) printk (kern_debug "scull:" FMT, # ARGs)
# Else/* this one for user space */
# Define pdebug (FMT, argS...) fprintf (stderr, FMT, # ARGs)
# Endif
# Else
# Define pdebug (FMT, argS...)/* Not debugging: nothing */
# Endif
# UNDEF pdebugg
# Define pdebugg (FMT, argS...)/* nothing: It's a placeholder */
The statement to be added in makefile:
# Comment/uncomment the following line to disable/enable debugging
DEBUG = y
# Add your debugging flag (or not) to cflags
Ifeq ($ (Debug), Y)
Debflags =-o-g-dscull_debug # "-o" is needed to expand inlines
Else
Debflags =-O2
Endif
Cflags + = $ (debflags)
To avoid too fast duplicate printk output and blocking the system, the kernel uses the following function to skip part of the output:
Int printk_ratelimit (void );
Typical applications are as follows:
If (printk_ratelimit ())
Printk (kern_notice "the printer is still on fire \ n ");
You can modify/proc/sys/kernel/printk_ratelimit (the number of seconds to wait before re-opening the information) and/proc/sys/kernel/printk_ratelimit_burst (the number of messages acceptable before the speed limit) to customize the printk_ratelimit behavior.
Linux also provides macros for printing device numbers (defined in ):
Int print_dev_t (char * buffer, dev_t Dev );
Char * format_dev_t (char * buffer, dev_t Dev );
The only difference between the two functions is: print_dev_t returns the number of printed characters, and format_dev_t returns the buffer pointer. Note that the size of the buffer char * buffer should be at least 20 B.
Iii. query and debugging
In most cases, the best way to obtain relevant information is to query the system information as needed, rather than continuously generating data.
Use the/proc file system
The/proc file system is a special file system created by software. The kernel uses it to export information to the outside world. Each file under/proc is bound to a kernel function. When you read the file, the function dynamically generates the file content. As previously used:
[Tekkaman2440 @ sbc2440v4] # Cat/proc/devices
Character devices:
1 mem
2 Pty
3 ttyp
4/dev/VC/0
4 tty
4 TTYs
5/dev/tty
5/dev/console
5/dev/ptmx
7 VCs
10 Misc
13 Input
14. Sound
81 video4linux
89 I2C
90 MTD
116 ALSA
128 PTM
136 PTS
180 USB
189 usb_device
204 s3c2410_serial
252 scull
253 usb_endpoint
254 rtc
Block devices:
1 ramdisk
256 RfD
7 Loop
31 mtdblock
93 nftl
96 inftl
179 MMC
The/proc module must be included, but the seq_file interface must be included.
For specific application methods, the source program and experiment are more effective.
For other debugging methods, such as GDB, LTT, and sysrq, in other books, such: detailed description of Embedded Linux System Development Technology-Based on ARM, building embedded Linux system, etc.
4. Source Code Experiment
Module Program link:
Module Program
Module test program link:
Module test program
Lab symptom:
[Tekkaman2440 @ sbc2440v4] # cd/lib/modules/
[Tekkaman2440 @ sbc2440v4] # insmod scull_debug.ko scull_nr_devs = 1 scull_quantum = 6 scull_qset = 2
[Tekkaman2440 @ sbc2440v4] # cd/tmp/
[Tekkaman2440 @ sbc2440v4] #./scull_test
Write code = 6
Write code = 6
Write code = 6
Write code = 2
Read code = 6
Read code = 6
Read code = 6
Read code = 2
[0] = 0 [1] = 1 [2] = 2 [3] = 3 [4] = 4
[5] = 5 [6] = 6 [7] = 7 [8] = 8 [9] = 9
[10] = 10 [11] = 11 [12] = 12 [13] = 13 [14] = 14
[15] = 15 [16] = 16 [17] = 17 [18] = 18 [19] = 19
[Tekkaman2440 @ sbc2440v4] # cd/proc/
[Tekkaman2440 @ sbc2440v4] # ls
1 751 running line kallsyms stat
2 769 CPU kmsg swaps
3 77 cpuinfo loadavg sys
4 778 crypto locks sysrq-trigger
5 779 devices meminfo sysvipc
59 78 diskstats MISC timer_list
6 781 driver modules tty
60 783 execdomains mounts uptime
63 785 filesystems MTD version
65 79 FS net vmstat
707 80 ide partitions yaffs
708 819 interrupts scullmem zoneinfo
709 asound iomem scullseq
710 buddyinfo ioports self
742 bus IRQ slabinfo
[Tekkaman2440 @ sbc2440v4] # Cat scullmem
Device 0: qset 2, q 6, SZ 20
Item at c071ebd4, qset at c071ef7c
Item at c071ef14, qset at c071eee0
0: c071eeac
1: c071ee78
[Tekkaman2440 @ sbc2440v4] # Cat scullseq
Device 0: qset 2, q 6, SZ 20
Item at c071ebd4, qset at c071ef7c
Item at c071ef14, qset at c071eee0
0: c071eeac
1: c071ee78
[Tekkaman2440 @ sbc2440v4] # rmmod scull_debug
[Tekkaman2440 @ sbc2440v4] # ls
1 742 buddyinfo iomem self
751 bus ioports slabinfo
3 769 running line IRQ stat
4 77 CPU kallsyms swaps
5 778 cpuinfo kmsg sys
59 779 crypto loadavg sysrq-trigger
6 78 devices locks sysvipc
60 781 diskstats meminfo timer_list
63 783 driver MISC tty
65 785 execdomains modules uptime
707 79 filesystems mounts version
708 80 fs mtd vmstat
709 824 ide net yaffs
710 asound interrupts partitions zoneinfo