Как проверить, является ли процесс неблокирующим в 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
- на самом деле результат хуже, потому что почти все системные вызовы являются точкой упреждения, где ядро может в любом случае переключать контекст.
Этот разработчик тратит впустую энергию, циклы ЦП, которые могут быть использованы для простоя потоков, и на самом деле не получает никаких преимуществ, которые он / она получает, делая это таким образом.
Если разработчик хочет быть дружественным к "строке кэша", прикрепите его задачи к определенному процессору и покончите с этим.