287 reading comments (0)
Favorites
Report
Linux Device Driver ------ printk in debugging technology
In Linux, the system information is displayed in the following three situations:
1. If the system only runs klogd, You can restart klogd through klogd-C and set lele_loglevel. Then, all information smaller than lele_loglevel will be printed to the console;
2. If the system only runs Syslogd, the message will not be transmitted to the user space. You can only view the message by reading/proc/kmsg;
3. If both klogd and syslogd are allowed in the system, any messages will be appended to the file/var/log/messages when messages are filtered and printed to the Console Based on lele_loglevel.
The printk statement output must be used to write the driver in Linux. One of the differences between the printk and the general printf statement is that the printk depends on the additional log level (loglevel ), or message level, to indicate the severity of messages.
For example: printk (kern_debug "Hi, my printk !");
The output information of the preceding statement is debug-level. Note that the content in kern_debug and the quotation marks cannot be separated by commas. Otherwise, an error will be reported during compilation!
Linux defines eight available log-level strings in the header file <Linux/kernel. h>, sorted by severity as follows:
Kern_emerg kern_alert kern_crit kern_err
Kern_warning kern_notice kern_info kern_debug
Printk statements with no log level specified use the default level, that is, the macro default_message_loglevel specified in kernel/printk. C. This macro is usually kern_warning.
In addition, the console (generally a text terminal or a serial port) also has an integer variable indicating the level, called console_loglevel. The initial value after the system is started is default_console_loglevel.
The kernel compares the log level of information in the program with lele_loglevel. The information is displayed only when the log level of the information is smaller than the value of the integer variable console_loglevel.
Therefore, we need to adjust the console_loglevel of the system to an appropriate value in advance so that the console correctly displays the information we need. For example, in the above statement "Hi, my first printk !", If the lele_loglevel value is not modified, it cannot be displayed on the control terminal.
There are two ways to modify: one is to modify through sys_syslog system call; the other is to use dmesg to modify or modify the first line in the/proc/sys/kernel/printk file, for example, dmesg-N 1 (1 in the command is the lele_loglevel value to be set. In fact, the preceding kern_emerg to kern_debug is the integer from 0 to 7 ). The former is temporary, and console_logleve will return to the default status after the system is restarted, while the latter is permanent, as long as the console_loglevel value is modified with dmesg, then it will always be the value.
I chose the former because I didn't want to change the system state at will, and the author of Linux Device drvier3 also provided a small program called setlevel, you can set the lele_loglevel through the executable file compiled by this program, which is very convenient.
But now the problem is that the setlevel. C provided by Linux Device driver3 cannot be compiled on the 2.6.20 kernel. during compilation, the prompt is: expected declaration specifiers or '... 'Before Syslog
The code in setlevel. C is as follows:
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <errno. h>
/* # Include <unistd. h> * // * conflicting on the Alpha */
# 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 );
}
Obviously, the problem occurs on _ syscall3.
In the program, the _ syscall3 (INT, syslog, Int, type, char *, bufp, Int, Len) statement is used to tell the compiler that the required system call is syslog, the return value is int, while the subsequent string is the three parameters and their types required by syslog.
However, setlevel. C cannot be compiled because the author of Linux Device driver3 writes this program in Linux kernel 2.6.10, but the _ syscall3 function is not defined in Linux kernel 2.6.20. (I have compiled setlevel. c In Red Hat 9.0 (2.4 kernel) and can pass it normally .)
So as long as the prototype is defined before _ syscall3 is called in setlevel. C, setlevel. C can be compiled and used normally. The setlevel. C after the code is added is as follows:
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <errno. h>
# Include <sys/syscall. h>/* This header file must be added. Otherwise, compilation fails */
# DEFINE _ syscall_return (type, Res )/
Do {/
If (unsigned long) (RES)> = (unsigned long) (-125 )){/
Errno =-(RES );/
Res =-1 ;/
}/
Return (type) (RES );/
} While (0)
# DEFINE _ syscall3 (type, name, type1, arg1, type2, arg2, type3, arg3 )/
Type name (type1 arg1, type2 arg2, type3 arg3 )/
{/
Long _ res ;/
_ ASM _ volatile ("int $0x80 "/
: "= A" (_ res )/
: "0" (_ nR _ # name), "B" (long) (arg1), "C" (long) (arg2 )),/
"D" (long) (arg3 )));/
_ Syscall_return (type ,__ res );/
}
_ 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 );
}
Http://blog.csdn.net/cumtzhj/article/details/6466704
Linux Device Driver ------ printk in debugging technology
In Linux, the system information is displayed in the following three situations:
1. If the system only runs klogd, You can restart klogd through klogd-C and set lele_loglevel. Then, all information smaller than lele_loglevel will be printed to the console;
2. If the system only runs Syslogd, the message will not be transmitted to the user space. You can only view the message by reading/proc/kmsg;
3. If both klogd and syslogd are allowed in the system, any messages will be appended to the file/var/log/messages when messages are filtered and printed to the Console Based on lele_loglevel.
The printk statement output must be used to write the driver in Linux. One of the differences between the printk and the general printf statement is that the printk depends on the additional log level (loglevel ), or message level, to indicate the severity of messages.
For example: printk (kern_debug "Hi, my printk !");
The output information of the preceding statement is debug-level. Note that the content in kern_debug and the quotation marks cannot be separated by commas. Otherwise, an error will be reported during compilation!
Linux defines eight available log-level strings in the header file <Linux/kernel. h>, sorted by severity as follows:
Kern_emerg kern_alert kern_crit kern_err
Kern_warning kern_notice kern_info kern_debug
Printk statements with no log level specified use the default level, that is, the macro default_message_loglevel specified in kernel/printk. C. This macro is usually kern_warning.
In addition, the console (generally a text terminal or a serial port) also has an integer variable indicating the level, called console_loglevel. The initial value after the system is started is default_console_loglevel.
The kernel compares the log level of information in the program with lele_loglevel. The information is displayed only when the log level of the information is smaller than the value of the integer variable console_loglevel.
Therefore, we need to adjust the console_loglevel of the system to an appropriate value in advance so that the console correctly displays the information we need. For example, in the above statement "Hi, my first printk !", If the lele_loglevel value is not modified, it cannot be displayed on the control terminal.
There are two ways to modify: one is to modify through sys_syslog system call; the other is to use dmesg to modify or modify the first line in the/proc/sys/kernel/printk file, for example, dmesg-N 1 (1 in the command is the lele_loglevel value to be set. In fact, the preceding kern_emerg to kern_debug is the integer from 0 to 7 ). The former is temporary, and console_logleve will return to the default status after the system is restarted, while the latter is permanent, as long as the console_loglevel value is modified with dmesg, then it will always be the value.
I chose the former because I didn't want to change the system state at will, and the author of Linux Device drvier3 also provided a small program called setlevel, you can set the lele_loglevel through the executable file compiled by this program, which is very convenient.
But now the problem is that the setlevel. C provided by Linux Device driver3 cannot be compiled on the 2.6.20 kernel. during compilation, the prompt is: expected declaration specifiers or '... 'Before Syslog
The code in setlevel. C is as follows:
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <errno. h>
/* # Include <unistd. h> * // * conflicting on the Alpha */
# 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 );
}
Obviously, the problem occurs on _ syscall3.
In the program, the _ syscall3 (INT, syslog, Int, type, char *, bufp, Int, Len) statement is used to tell the compiler that the required system call is syslog, the return value is int, while the subsequent string is the three parameters and their types required by syslog.
However, setlevel. C cannot be compiled because the author of Linux Device driver3 writes this program in Linux kernel 2.6.10, but the _ syscall3 function is not defined in Linux kernel 2.6.20. (I have compiled setlevel. c In Red Hat 9.0 (2.4 kernel) and can pass it normally .)
So as long as the prototype is defined before _ syscall3 is called in setlevel. C, setlevel. C can be compiled and used normally. The setlevel. C after the code is added is as follows:
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <errno. h>
# Include <sys/syscall. h>/* This header file must be added. Otherwise, compilation fails */
# DEFINE _ syscall_return (type, Res )/
Do {/
If (unsigned long) (RES)> = (unsigned long) (-125 )){/
Errno =-(RES );/
Res =-1 ;/
}/
Return (type) (RES );/
} While (0)
# DEFINE _ syscall3 (type, name, type1, arg1, type2, arg2, type3, arg3 )/
Type name (type1 arg1, type2 arg2, type3 arg3 )/
{/
Long _ res ;/
_ ASM _ volatile ("int $0x80 "/
: "= A" (_ res )/
: "0" (_ nR _ # name), "B" (long) (arg1), "C" (long) (arg2 )),/
"D" (long) (arg3 )));/
_ Syscall_return (type ,__ res );/
}
_ 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 );
}
Http://blog.csdn.net/cumtzhj/article/details/6466704