I have been studying the QEMU disk IO path source code, found that the direct view is very inefficient, QEMU is a big guy (the source part is about 154MB, completely by the C language), the whole structure is very complex, So the best way to study Qemu from code is to debug it. Constantly collect more debug information to get the truth of the source code.
Many people's first reaction may be to use some similar to eclipse, GDB this kind of powerful debugger, I certainly no exception, after a morning after the use of Eclipse or gdb of the ideological struggle of the private sentiment, I came to understand that the original two of my tools will not use AH!! (Heavy fog
After the boss's warning, he said that he used to use GDB to debug Xen's effect is not ideal, and because we use the experimental environment has been no xwindows centos7-miminal, so the use of eclipse is a torment, They used to use output debugging information to generate function call log for function tracking and debug, which may really be a very primitive, very concise way of thinking, sometimes the most effective is perhaps the most simple rough method?
Specific debugging methods I did not ask more questions, I would like to try, and then began their own thinking of the Debug method concept.
At first, I took for granted the printf function, but this function in a single source file program is completely feasible and simple, a running program, you can be allowed to print out the shell of debugging information. Then found that using prtintf is really naive ah naive!! When I built this idea to use in a need to read a file in a multi-source file inside the time to find out, C language powerful place in the world with the most complex software system almost only in C language to complete, but when we need to meet the daily use of C language will feel a little overkill, Far less than shell script and Python-type scripting languages.
Well, before the boss mentioned to do a similar with the OUTPUT function call log file of things, so, in order to facilitate our observation of the output of the log message, we need to output the function call log message into a file, OK, we now to analyze what this log file needs to have what kind of function? Using the features of MySQL output log file, we summarize the following several
1. Each log output requires a timestamp of information, including the year, day, month, hour, minute, and second.
2. Each log output must be with the well-accurate information of the function of the FILE_NAME-FUN1-FUN2-FUN3, whose information represents Fun3 was fun2 called Fun3 was fun1 called Fun1 contained in the file_name file.
3. Each log output has the data information that is carried by the function being traced, such as data volume, data value, etc...
After several modifications and debugs, I wrote the following printf_debug function:
1#include <stdio.h>2#include <stdlib.h>3#include <fcntl.h>4#include <time.h>5#include <string.h>6 /*----------------debug_function--------------*/7 voidPrintf_debug (Char*path,Char*functionname,8 intneeddata[])9 {Ten structtm*p; One time_t TIMEP; ATime (&TIMEP); -p = gmtime (&TIMEP); - Chars[ -] =""; the intFD = open (Path,o_rdwr | O_creat |O_append, -S_IRUSR |s_iwusr); -sprintf (S+strlen (s),"%s%d/%d/%d/%d:%d:%d \ n", -FunctionName, (1900+p->tm_year), (1+p->tm_mon),p->Tm_mday, +P->tm_hour, P->tm_min, p->tm_sec); -sprintf (S+strlen (s),"Config_linux_aio is%d \ Use_aio is%d \ n", needdata[0],needdata[1]); +Write (Fd,s,sizeof(s)); A Close (FD); at}
Write here I can't wait to throw this function into Qemu's source for debugging, the eldest brother began to call me to trace several functions, I can't wait to put the definition of this function into the source code of the development of the file, Hua Hua to put these several functions in front of the tracking function .... What followed was ....
Boss sometimes called me to turn off this function, independently opened another function, and occasionally called me to restore the source code re-adjust ....
Horizontal Groove horizontal Groove bedroom!!!! ,
That source file nearly 3000 lines of code, and each need to trace the interval between the function is also relatively large, each need to block or delete the changes are extremely painful, in order to solve the problem of egg pain, I began to re-conceive the structure of the debug function, Since I can only do coding and reading under the command-line text editor of Vim, it is inconvenient to quickly copy and paste the visual
So every time you need to debug the large-scale modification and deletion of the function, it is best to focus the operation area in a relatively small area inside, and then after the depth of the idea, then decided to use the C language inside the macro definition to meet my needs, and after the cranky change, got the following ideas:
Here I introduce a debugallow parameter for the Printf_debug function, if the Debugallow is 0, it means the printf_debug is forbidden,
1 voidPrintf_debug (Char*path,Char*functionname,2 intDebugallow,intneeddata[])3 {4 if(Debugallow = =0) 5 return ;6 structtm*p;7 time_t TIMEP;8Time (&TIMEP);9p = gmtime (&TIMEP);Ten Chars[ -] =""; One intFD = open (Path,o_rdwr | O_creat |O_append, AS_IRUSR |s_iwusr); -sprintf (S+strlen (s),"%s%d/%d/%d/%d:%d:%d \ n", -FunctionName, (1900+p->tm_year), (1+p->tm_mon),p->Tm_mday, theP->tm_hour, P->tm_min, p->tm_sec); -sprintf (S+strlen (s),"Config_linux_aio is%d \ Use_aio is%d \ n", needdata[0],needdata[1]); -Write (Fd,s,sizeof(s)); - Close (FD); +}
Then I define a macro for each function that needs to be traced separately:
1 #define Allow_raw_open 12#define allow_raw_reopen_prepare 13#define allow_handle_aiocb_rw_vector 14#define allow_handle_aiocb_rw_linear 15#define Allow_laio_submit 16#define allow_paio_submit 1
All we need to do is insert these macros into the debugallow of the corresponding trace function Printf_debug.
For example, we need to trace the following functions
1 return paio_submit (BS, s->FD, Sector_num, Qiov, Nb_sectors,2 cb, opaque, type);
Just add the corresponding Printf_debug function in front:
1 Printf_debug (Path_paio_submit, "raw-posix.c-raw_aio_submit-paio_submit", 2 allow_paio_submit, 0); 3 return paio_submit (BS, s->FD, Sector_num, Qiov, Nb_sectors,4 cb, Opaque, Type);
When we need to block out the Printf_debug function of Paio_submit, as long as the allow_paio_submit in the previous macro definition is set to 0. When you need to modify the masking of multiple printf_debug functions, simply focus on the code block of the previously defined macro. This reduces the range of operations from 3000 lines to 6 rows.
When we need to focus on all the debug functions, we might as well define one more macro
1 #define Debug_qemu_io_mode
We can use this macro to control the existence of all printf_debug functions at once, such as
12 printf_debug (path_paio_submit, "Raw-posix.c-raw_aio_submit-paio_ Submit",3 allow_paio_submit, needdata); 4 #endif 5 return paio_submit (BS, s->FD, Sector_num, Qiov, Nb_sectors,6 CB, Opaque, Type);
When we need to clear out all the Printf_debug functions, just remove the first definition of Debug_qemu_io_mode.
The above is the use of all today used to debug tracing the QEMU disk IO source code scheme, the following is the use of all the source code
1 /*---------------------------------*/2 /*------Debug_qemu_io_mode---------*/3 4 5 6 #defineDebug_qemu_io_mode/*---Open or close the debug mode*/7 8#ifdef Debug_qemu_io_mode9 Ten #defineAllow_raw_open 1 One #defineAllow_raw_reopen_prepare 1 A #defineAllow_handle_aiocb_rw_vector 1 - #defineAllow_handle_aiocb_rw_linear 1 - #defineAllow_laio_submit 1 the #defineAllow_paio_submit 1 - - Char*path_raw_reopen_prepare ="/tmp/raw_reopen_prepare.log"; - #definePath_handle_aiocb_rw_vector + #definePath_raw_open - #definePath_handle_atiocb_rw_rw_linear + Char*path_laio_submit ="/tmp/laio-submit.log"; A Char*path_paio_submit ="/tmp/paio-submit.log"; at#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <time.h> -#include <string.h> - /*----------------debug_function--------------*/ in voidPrintf_debug (Char*path,Char*functionname, - intDebugallow,intneeddata[]) to { + if(Debugallow = =0) - return ; the structtm*p; * time_t TIMEP; $Time (&TIMEP);Panax Notoginsengp = gmtime (&TIMEP); - Chars[ -] =""; the intFD = open (Path,o_rdwr | O_creat |O_append, +S_IRUSR |s_iwusr); Asprintf (S+strlen (s),"%s%d/%d/%d/%d:%d:%d \ n", theFunctionName, (1900+p->tm_year), (1+p->tm_mon),p->Tm_mday, +P->tm_hour, P->tm_min, p->tm_sec); -sprintf (S+strlen (s),"Config_linux_aio is%d \ Use_aio is%d \ n", needdata[0],needdata[1]); $Write (Fd,s,sizeof(s)); $ Close (FD); - } - /*----------------------------------------*/ the /*----------------------------------------*/
#endif
A method for tracing the path of the QEMU source function