LINUX.ORG.RU

poll и epoll(...) и x86 WAIT/FWAIT

 , ,


0

1

Подскажите, где найти реализацию poll syscall на уровне машинных команд?
Можно ли получить такой листинг с помощью gcc -S на простейшем примере кода, где есть вызов poll()?
Если нет, то какие файлы ядра посмотреть? Поглядел /usr/src/linux-source-4.9/include/linux/poll.h - там ничего, напоминающего ассемблерный код, нет.

И ещё. Как poll связан с x86-инструкцией WAIT/FWAIT? Реализован ли poll() через прерывания процессора?

Или происходит сохранение контекста процесса (нити), переключение выполнения на другой участок кода?
В процессоре 80286 или 80386 были для этого инструкции ENTER / LEAVE.

https://www.opennet.ru/man.shtml?category=2&topic=poll

Отвечу от имени KO:

Подскажите, где найти реализацию poll syscall на уровне машинных команд?

В коде ядра Linux, но (WTF) зачем?

Можно ли получить такой листинг с помощью gcc -S на простейшем примере кода, где есть вызов poll()?

Там будет вызов ядерного poll (т.е. подготовка параметров и инструкция syscall/int), но не реализация. Вот пример исходного кода функции poll() с вызовом poll-syscall.

Если нет, то какие файлы ядра посмотреть? Поглядел /usr/src/linux-source-4.9/include/linux/poll.h - там ничего, напоминающего ассемблерный код, нет.

Вот тут исходный код poll и других родственных syscall-ов. Получить его в виде инструкций CPU несложно (например посредством objdump).

И ещё. Как poll связан с x86-инструкцией WAIT/FWAIT?

Никак не связан, от слова совсем.

Реализован ли poll() через прерывания процессора?

Системный вызов ядра может выполнятся из user-mode библиотеки (glibc, ulibc, musl) как посредством syscall инструкции, так и через программное прерывание. Саму инструкцию syscall также можно рассматривать как вариант программного прерывания.

Программные прерывания внутри ядра примерно не используются, ибо unreasonable.

Механизм аппаратных прерываний является основой, на которой строится диспетчеризация процессов и вытесняющая многозадачность во всех релевантных ОС.

Deleted ()
Последнее исправление: Deleted (всего исправлений: 1)

Какая-то каша в голове. При чем тут ассемблер, x86, контекст, прерывания? poll написан на C, это высокоуровневая логика.

Можно ли получить такой листинг с помощью gcc -S на простейшем примере кода, где есть вызов poll()?

Подумай о разнице между вызовом и реализацией. И вообще подумай, ты будто не про poll(2) пишешь, всё не в тему.

anonymous ()

Или происходит сохранение контекста процесса (нити), переключение выполнения на другой участок кода?

Да, если нет повода сразу вернуться из poll по готовности одного и fd.

В процессоре 80286 или 80386 были для этого инструкции ENTER / LEAVE.

Это из другой оперы. Для сохранения/восстановления контекста используются XSAVE / XSAVEOPT / XRSTOR / XSSTORS.

Deleted ()

ENTER/LEAVE - это же вообще не к месту. Это инструкции для языков высокого уровня.

Например, в Паскале есть такая вещь, как вложенные друг в друга функции. Причем вложенная функция может обращаться к локальным переменным «внешней» функции. Инструкция ENTER создает на стеке специальные структуры данных, чтобы вложенные функции разных уровней вложенности могли обращаться к любым локальным переменным своих «внешних» функции.

bigbit ★★★★★ ()
Ответ на: комментарий от Deleted

Что-то почитал я про XSAVE*/XRSTOR* - они ведь только всякую экзотику сохраняют, типа SSE/AVX/MPX…

А нормальные регистры (*ax, *bx, *cx, *dx, *di, *di, и т.д.), насколько я знаю, сохраняются чисто программно операциями MOV. Если я не прав и отстал от жизни - поправьте.

bigbit ★★★★★ ()
Ответ на: комментарий от bigbit

Что-то почитал я про XSAVE*/XRSTOR* - они ведь только всякую экзотику сохраняют, типа SSE/AVX/MPX…

А нормальные регистры (*ax, *bx, *cx, *dx, *di, *di, и т.д.), насколько я знаю, сохраняются чисто программно операциями MOV. Если я не прав и отстал от жизни - поправьте.

Все верно.

Регистры общего пользования нерационально сохранять/восстанавливать одной командой (это показал опыт использования pusha / pushad / popa / popad). Часть регистров сохраняется по стеку вызовов, часть используется особенным образом. Оставшиеся проще обслужить обычными mov-ами, нежели городить отдельнсую CISC-инструкцию (которая все равно будет выполняться через микрокод).

В свою очередь XSAVE*/XRSTOR* тоже работают через микрокод, но избавляют от нобходимости знать все features (включая размер данных), проверки этих features через флажки cpuid, и кучи соответствующих переходов.

Deleted ()

Реализован ли poll() через прерывания процессора?

poll реализован через ожидание. Процесс проверяет, что событие не наступило, добавляет себя в очередь ожидания и засыпает (уходит с процессора – планировщик переключается на другой процесс).

Другой процесс, когда событие наступает, будит один/все процессы из очереди ожидания (помечает в планировщике, как доступные для исполнения).

ttnl ★★★★★ ()
Последнее исправление: ttnl (всего исправлений: 1)
Ответ на: комментарий от example_cat

не может человек знающий про FWAIT не знать что делает инструкция.

Я лишь бегло в молодости читал книгу Б. Э. Смит, М. Т. Джонсон. Архитектура и программирование микропроцессора INTEL 80386 / Пер. с англ. В. Л. Григорьева. - М. : ТОО «Конкорд», 1992. - 334 с. : ил. - ISBN 5-87737-004-9

Поэтому про WAIT знаю поверхностно - на практике его не использовал. Я хотел спросить, что используется в современных процессорах для poll().

В школьные годы пытался эмулировать многозадачность в реальном режиме 80286 для алгоритма компьютерной игры, но знаний не хватило. У меня тогда алгоритм получился с блокирующими вызовами процедур.

BruteForceSSL ()