2016-12-28 17 views
2

FIO поддерживает целую кучу Io двигателей - все поддерживаемые двигатели присутствуют здесь: https://github.com/axboe/fio/tree/master/enginesКак fio загружает различные двигатели io при запуске?

Я пытался понять внутренние механизмы FIO работ и застрял на том, как FIO загружает все Io двигателей.

Например, я видеть каждый двигатель имеет метод регистрации и отмены регистрации себя, например, регистры sync.c и отменяет регистрацию с использованием следующих методов

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

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

Мой вопрос: кто называет эти методы?

Чтобы найти ответ, который я попытался запустить FIO под БГД - поставил точку останова в fio_syncio_register и в основной функции, fio_syncio_register вызывается еще до основной, который говорит мне, что это что-то делать с __libc_csu_init и трассировку подтвердил, что

(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() 

я провел некоторое время читал о __libc_csu_init и __libc_csu_fini и каждый отдельный описание говорит о методах, украшенных __attribute__((constructor)) будет вызываться перед основным, но в случае FIO sync.c я не вижу fio_syncio_register украшены __attribute__

Может кто-нибудь, пожалуйста, помогите мне понять, как работает этот поток? Есть ли другие материалы, которые я должен читать, чтобы понять это?

Thanks

ответ

0

Интересный вопрос. Я не мог понять, ответ, глядя на источник, так вот шаги, которые я взял:

$ 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 

Это говорит нам о том, что глобальные инициализаторы присутствуют в этом объекте. Они вызываются при запуске программы. Кто они такие?

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

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

Интересно. Существует, по-видимому, специальный раздел .text.startup. Что в ней?

$ 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 
... 

Почему именно эта функция мы ищем. Но как это закончилось в этом специальном разделе? Чтобы ответить на это, мы можем посмотреть на предварительно обработанный источник (в ретроспективе, я должен был бы начал с).

Как мы можем его получить? Командная строка для компиляции sync.o скрыта. Глядя в Makefile, мы можем отобразить командную строку с QUIET_CC=''.

$ 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 

Теперь мы знаем, командную строку, и может производить препроцессированный файл:

$ 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 

Глядя в /tmp/sync.i, мы видим:

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

Хм, это является__attribute__((constructor)) в конце концов , Но как он туда попал? Ага! Я пропустил fio_init на this line:

static void fio_init fio_syncio_register(void) 

Что fio_init баллотироваться? Опять же в /tmp/sync.i:

#define fio_init __attribute__((constructor)) 

Так , что как это работает.

+0

Ничего себе, я бы никогда не подумал об этом, спасибо вам большое за это усилие. – nachiappan