Назад | Перейти на главную страницу

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

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

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

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

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

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

Значение для неблокирующего сокета - 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 - по сути, результат хуже потому что почти все системные вызовы - это точка прерывания, где ядро ​​все равно может переключить вас контекстом.

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

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