2016-12-28 7 views
2

fio unterstützt eine ganze Reihe von io-Motoren - alle unterstützten Motoren vorhanden sind hier: https://github.com/axboe/fio/tree/master/enginesWie fio lädt verschiedene io-Motoren, wenn es startet?

Ich habe versucht, die Interna wie fio Werke zu verstehen und blieb stecken, wie fio Lasten aller io-Motoren.

Zum Beispiel I Jeder Motor hat eine siehe Methode selbst zu registrieren und deregistrieren, beispielsweise sync.c Register und hebt die Registrierung unter Verwendung der folgenden Methoden

fio_syncio_register: https://github.com/axboe/fio/blob/master/engines/sync.c#L448

und fio_syncio_unregister: https://github.com/axboe/fio/blob/master/engines/sync.c#L461

Meine Frage ist, wer diese Methoden ruft?

Antwort zu finden Ich habe versucht fio unter gdb läuft - einen Haltepunkt in fio_syncio_register platziert und in der Hauptfunktion, wird fio_syncio_register schon vor Haupt genannt, was mich etwas mit __libc_csu_init und Backtrace bestätigt zu tun hat, sagt, dass

(gdb) bt 
#0 fio_syncio_register() at engines/sync.c:450 
#1 0x000000000047fb9d in __libc_csu_init() 
#2 0x00007ffff6ee27bf in __libc_start_main (main=0x40cd90 <main>, argc=2, argv=0x7fffffffe608, init=0x47fb50 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe5f8) 
    at ../csu/libc-start.c:247 
#3 0x000000000040ce79 in _start() 

ich irgendwann verbrachte Lesung über __libc_csu_init und __libc_csu_fini und jede einzelne Beschreibung spricht über Methoden mit __attribute__((constructor)) dekoriert wird vor dem Haupt genannt werden, aber im Fall von FIO sync.c ich sehe nicht fio_syncio_register verziert mit __attribute__

Kann mir bitte jemand helfen, zu verstehen, wie dieser Fluss funktioniert? Gibt es andere Materialien, die ich lesen sollte, um das zu verstehen?

Danke

Antwort

0

Interessante Frage. Ich konnte nicht die Antwort herauszufinden, an der Quelle suchen, so sind hier die Schritte, die ich nahm:

$ make 
$ find . -name 'sync.o' 
./engines/sync.o 

$ readelf -WS engines/sync.o | grep '\.init' 
    [12] .init_array  INIT_ARRAY  0000000000000000 0021f0 000008 00 WA 0 0 8 
    [13] .rela.init_array RELA   0000000000000000 0132a0 000018 18  36 12 8 

Dies sagt uns, dass die globale initializers in diesem Objekt vorhanden ist. Diese werden beim Programmstart aufgerufen. Was sind Sie?

$ objdump -Dr engines/sync.o | grep -A4 '\.init' 
Disassembly of section .init_array: 

0000000000000000 <.init_array>: 
    ... 
      0: R_X86_64_64 .text.startup 

Interessant. Es gibt anscheinend einen speziellen .text.startup Abschnitt. Was ist drin?

$ objdump -dr engines/sync.o | less 
... 
Disassembly of section .text.startup: 

0000000000000000 <fio_syncio_register>: 
    0: 48 83 ec 08    sub $0x8,%rsp 
    4: bf 00 00 00 00   mov $0x0,%edi 
         5: R_X86_64_32 .data+0x380 
    9: e8 00 00 00 00   callq e <fio_syncio_register+0xe> 
         a: R_X86_64_PC32  register_ioengine-0x4 
... 

Warum ist es genau die Funktion, die wir suchen. Aber wie ist es in diesem speziellen Bereich gelandet? Um das zu beantworten, können wir uns die vorverarbeitete Quelle ansehen (im Rückblick hätte ich damit gestartet).

Wie können wir es bekommen? Die Befehlszeile zum Kompilieren von sync.o ist ausgeblendet. In Makefile suchen, können wir die Befehlszeile mit QUIET_CC='' aufdecken.

$ rm engines/sync.o && make QUIET_CC='' 
gcc -o engines/sync.o -std=gnu99 -Wwrite-strings -Wall -Wdeclaration-after-statement -g -ffast-math -D_GNU_SOURCE -include config-host.h -I. -I. -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DBITS_PER_LONG=64 -DFIO_VERSION='"fio-2.16-5-g915ca"' -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DFIO_INTERNAL -DFIO_INC_DEBUG -c engines/sync.c 
    LINK fio 

Jetzt wissen wir die Kommandozeile und kann vorverarbeiteten Datei erzeugen:

$ gcc -E -dD -std=gnu99 -ffast-math -D_GNU_SOURCE -include config-host.h -I. -I. -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DBITS_PER_LONG=64 -DFIO_VERSION='"fio-2.16-5-g915ca"' -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DFIO_INTERNAL -DFIO_INC_DEBUG engines/sync.c -o /tmp/sync.i 

in /tmp/sync.i Sehen, sehen wir:

static void __attribute__((constructor)) fio_syncio_register(void) 
{ 
register_ioengine(&ioengine_rw); 
register_ioengine(&ioengine_prw); 
... 

Hmm, es ist__attribute__((constructor)) schließlich . Aber wie ist es dahin gekommen? Aha! Ich vermisste die fio_init auf this line:

static void fio_init fio_syncio_register(void) 

Was fio_init nicht stehen? Wieder in /tmp/sync.i:

#define fio_init __attribute__((constructor)) 

So dass ist, wie es funktioniert.

+0

Wow, ich hätte das nie herausgefunden, vielen Dank für diese Mühe. – nachiappan

Verwandte Themen