Como verificar se um processo não está bloqueando no linux sem usar um rastreador de pilha?

4

Um servidor multi-cpu está executando vários processos. Um processo tem um thread que deve estar sempre em um estado de rotação, usando 100% da CPU que foi atribuída. Meu método atual (além de perguntar ao desenvolvedor ...) está usando strace no processo que espera que as informações cheguem ao seu descritor de arquivo aberto e o verifica continuamente usando recvfrom(2) em que erno está definido como EAGAIN e método está retornando -1 quando nenhum pacote deve ser lido do soquete da rede.

Não me sinto confortável com as configurações de produção de rastreamento de pilha, e é uma maneira complicada de determinar essas informações na melhor das hipóteses. Eu estava cutucando sobre proc(5) e pensei que o valor do campo flags em /proc/[pid]/fdinfo poderia ser útil para verificar se esse processo estava usando um soquete que chamou open(2) com o modo O_NONBLOCK .

Estou lutando para fazer engenharia reversa desse valor no momento. Eu sei que representa o OR bit a bit do status do arquivo e do modo de arquivo. Por isso, acho que posso verificar os cabeçalhos de origem para o valor das constantes open(2) usa nesse kernel específico e, em seguida, use-os com bit a bit até encontrar um valor que corresponda ao que está em fdinfo . Isso parece um pouco desajeitado, se alguém puder validar o método acima (eu ainda não posso) ou fornecer uma solução mais elegante, eu ficaria muito grato.

Eu também sei que fnctl(2) pode definir um descritor de arquivo para um estado sem bloqueio, mas estou tratando o equivalente a abrir para o momento

    
por inetplumber 31.03.2014 / 23:35

1 resposta

11

Sim, esta é uma maneira válida de verificar se o soquete não está bloqueando.

O valor para um soquete sem bloqueio é 04000, soquetes não-bloqueantes em /proc/<pid>/fdinfo são representados em octal.

Você pode validar esse comportamento com 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

Então, agora você sabe como, devo salientar que seu desenvolvedor está fazendo errado . Se sockets sem bloqueio são algo que eles querem usar, tudo bem - no entanto, eles devem configurar um epoll(2) no socket e bloquear na enquete.

O programa ganha nada de read(2) em um soquete sem bloqueio que produz EAGAIN - na verdade, o resultado é pior porque quase todos As chamadas do sistema são um ponto de preempção onde o kernel pode mudar o contexto de qualquer maneira.

Esse desenvolvedor está perdendo energia, ciclos de CPU que podem ser usados para encadeamentos inativos e não está realmente ganhando nenhum benefício de fazer isso dessa maneira.

Se o desenvolvedor quiser ser amigável com "linha de cache", fixe suas tarefas a uma CPU específica e conclua o processo.

    
por 01.04.2014 / 00:28