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