Как проверить, является ли процесс неблокирующим в Linux без использования трассировщика стека?

Сервер с несколькими процессорами выполняет несколько процессов. Один процесс имеет поток, который всегда должен находиться в состоянии вращения, используя 100% ЦП, для которого он был назначен. Мой текущий метод (кроме того, чтобы спросить разработчика...) использует strace в процессе, который ожидает получения информации об открытом дескрипторе файла и постоянно проверяет ее, используя recvfrom(2) где erno установлен в EAGAIN и метод возвращает -1, когда из сетевого сокета не нужно читать никаких пакетов.

Мне неудобно отслеживать производственные настройки стека, и это в лучшем случае громоздкий способ определения этой информации. Я ковырялся proc(5) и подумал, что значение поля флагов в /proc/[pid]/fdinfo может быть полезно проверить, использует ли этот процесс сокет open(2) с O_NONBLOCK Режим.

Я изо всех сил пытаюсь реконструировать это значение в данный момент. Я знаю, что он представляет побитовое ИЛИ состояния файла и режима файла. Так что я думаю, что я могу проверить заголовки источника для значения констант open(2) использует в этом конкретном ядре, а затем побитовое ИЛИ их, пока я не найду значение, которое соответствует тому, что в fdinfo, Это кажется довольно неуклюжим, если кто-то может проверить приведенный выше метод (я пока не могу) или предложить более элегантное решение, я был бы очень признателен.

Я также знаю fnctl(2) может установить дескриптор файла в неблокирующее состояние, но я лечу этот эквивалент, чтобы открыть на данный момент

1 ответ

Решение

Да, это правильный способ проверить, что сокет не блокируется.

Значение для неблокирующего сокета - 04000, неблокирующие сокеты в /proc/<pid>/fdinfo представлены в восьмеричном виде.

Вы можете проверить это поведение с помощью Python.

Python 2.7.5 (default, Feb 19 2014, 13:47:28) 
[GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import *
>>> import os
>>> from os import O_NONBLOCK
>>> s = socket(AF_INET, SOCK_STREAM)
>>> s.setblocking(0)
>>> print open("/proc/self/fdinfo/{0}".format(s.fileno())).read(4096)
pos:    0
flags:  04002

>>> if 04002 & O_NONBLOCK:
...   print "yes"
... else:
...   print "no"
... 
yes

Итак, теперь вы знаете, как, я должен указать, что ваш разработчик делает это неправильно. Если неблокирующие сокеты - то, что они хотят использовать, это нормально - однако они должны установить epoll(2) вместо сокета и заблокировать опрос.

Программа ничего не получает от read(2) на неблокирующем сокете, который производит EAGAIN - на самом деле результат хуже, потому что почти все системные вызовы являются точкой упреждения, где ядро ​​может в любом случае переключать контекст.

Этот разработчик тратит впустую энергию, циклы ЦП, которые могут быть использованы для простоя потоков, и на самом деле не получает никаких преимуществ, которые он / она получает, делая это таким образом.

Если разработчик хочет быть дружественным к "строке кэша", прикрепите его задачи к определенному процессору и покончите с этим.

Другие вопросы по тегам