POSIX API

Тема в разделе "WASM.HEAP", создана пользователем Nafanya, 10 сен 2011.

  1. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    7mm

    Не могли бы вы показать системный вызов для API sendto() и API write() по исходникам glibc?
    Не выходит проследить путь от вызова API до INLINE_SYSCALL.
    К сожалению, нужно именно для sendto(), а не для send().
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    скиньте мне исходник __libc_dlopen_mode, а то чет kernel.org даун фор майнтенс, не могу сорцы скачать... хотел посмотреть, как реализован у них dlopen(NULL, ...)...
     
  3. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    Я понял вопрос, действительно - магия :)

    Но. Я вот смотрю в исходниках ядра линукса, там send реализован через sendto (см. net/socket.c). Кроме этого, для архитектуры x86_32 интерфейс сокетов реализован через один системный вызов sys_socketcall (см. arch/x86/kernel/syscall_table_32.S и net/socket.c). Для x86_64 есть sys_sendto, однако также нет sys_send.

    Таким образом, получается, что в glibc для linux будет реализация send либо через sendto (x86_64, что и видно в INLINE_SYSCALL (sendto, ...)), либо через елиный интерфейс сокетов socketcall (x86_32).

    Как-то так :)
     
  4. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    Rel
    kernel.org поломали на днях, вы не в курсе? временно репозиторий ядра на github'е =)
     
  5. slesh

    slesh New Member

    Публикаций:
    0
    Регистрация:
    6 фев 2009
    Сообщения:
    214
    делаешь прогу где вписываешь свои функции, далее делаешь strace для проги и смотришь лог вызовов системных вызовов (жестоко звучит)
     
  6. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Загадка разгадана!
    У Posix API write() нет никакого тела в glibc и искать его там бессмысленно.
    Магии нет никакой, просто разработчики glibc используют хаки (dirty hacks - грязные трюки) при сборке и осложняют этим жизнь другим программистам.

    Вот полюбуйтесь:

    (echo '#include <sysdep-cancel.h>'; \
    echo 'PSEUDO (__libc_write, write, 3)'; \
    echo ' ret'; \
    echo 'PSEUDO_END(__libc_write)'; \
    echo 'libc_hidden_def (__libc_write)'; \
    echo 'weak_alias (__libc_write, __write)'; \
    echo 'libc_hidden_weak (__write)'; \
    echo 'weak_alias (__libc_write, write)'; \
    echo 'libc_hidden_weak (write)'; \
    ) | gcc -c "часть сроки пропущена" -o /root/research/glibc/io/write.o -
    .././scripts/mkinstalldirs /root/research/glibc/io

    При выполнении скрипта во время сборки налету создаётся файл - единица трансляции, содержащая тело неуловимой API-функции write():

    Код (Text):
    1. #include <sysdep-cancel.h>;
    2. PSEUDO (__libc_write, write, 3);
    3. ret;
    4. PSEUDO_END(__libc_write);
    5.  
    6. libc_hidden_def (__libc_write);
    7. weak_alias (__libc_write, __write);
    8. libc_hidden_weak (__write);
    9. weak_alias (__libc_write, write);
    10. libc_hidden_weak (write);
    Эта единица трансляции, отсутствующая в glibc, и передаётся gcc на компиляцию.

    Для x86-32 architecture имеем следующие результаты:
    1)API write() -> syscall №4

    from API write() body:
    Код (Text):
    1. mov     edx, [esp+8+arg_8]
    2. mov     ecx, [esp+8+arg_4]
    3. mov     ebx, [esp+8+arg_0]
    4. mov     eax, 4
    5. call    ds:_dl_sysinfo
    6. ------//------------//-------------------
    7. _dl_sysinfo     dd offset _dl_sysinfo_int80
    8. ---------//----------//------------------
    9. _dl_sysinfo_int80 proc near
    10. int     80h             ; LINUX
    11. retn
    12. _dl_sysinfo_int80 endp
    Этот экспериментально полученный листинг подтверждается теоретическими результатами:
    из /usr/include/asm/unistd_32.h -> #define __NR_write 4

    2) POSIX API: socket(), bind(), connect(), listen(), accept(), send(), recv(), sendto(), recvfrom(), sendmsg(), recvmsg() используют один syscall № 102. (из unistd_32.h -> #define __NR_socketcall 102 )

    from API sendto() body:
    Код (Text):
    1. mov     edx, ebx
    2. mov     eax, 66h
    3. mov     ebx, 0Bh
    4. lea     ecx, [esp+arg_0]
    5. call    ds:_dl_sysinfo
    Research Resume:
    Для архитектуры x86-32 сравниваемые POSIX API write() и sendto() не реализованы через один syscall ядра, а используют различные системные вызовы:
    write() -> №4
    sendto() -> №102.
    До границы входа в ядро эффективность участков кода данных API приблизительно одинакова.
    Таким образом схожесть функционального поведения различных API не может выступать в качестве гарантии использования ими одного и того же системного вызова.
     
  7. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    Для X86_32 sendto реализован через __NR_socketcall (102, arch/x86/include/asm/unistd_32.h). Кто говорил, что write и sendto это один и тот же системный вызов?! А вот socket, listen, accept, send, recv, recvfrom и пр. будут реализованы через тот же __NR_socketcall. Вы народ-то не путайте, перечитайте внимательнее мой пост #23. Для X86_64 ситуация с socketcall будет другая, там его нет, но есть отдельные номера системных вызовов для перечисленных операций (arch/x86/include/asm/unistd_64.h).
     
  8. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    7mm
    Естественно это не Вы говорили, а другие программисты. Но собственно из-за возникновения путаницы с sendto() и write() и начался этот simple research:)