如何在不使用堆栈跟踪器的情况下检查进程在 linux 中是否非阻塞?

ine*_*ber 5 linux kernel blocking socket

多 CPU 服务器正在运行多个进程。一个进程有一个线程应该始终处于旋转状态,使用它分配的 CPU 的 100%。我当前的方法(除了询问开发人员...)正在strace等待信息到达其打开的文件描述符的进程上使用recvfrom(2)erno并使用where设置为连续检查它,EAGAIN并且方法在没有数据包时返回 -1从网络套接字。

我不习惯堆栈跟踪生产设置,这是一种确定这些信息的笨拙方法。我正在proc(5)探索并认为标志字段的值/proc/[pid]/fdinfo可能有助于检查该进程是否正在使用open(2)以该O_NONBLOCK模式调用的套接字。

我目前正在努力对这个值进行逆向工程。我知道它代表文件状态和文件模式的按位或。所以我想我可以检查源头文件中常量open(2)在那个特定内核上使用的值,然后按位或它们,直到我找到一个与fdinfo. 这看起来很笨拙,如果有人可以验证上述方法(我还不能)或提供更优雅的解决方案,我将非常感激。

我也知道fnctl(2)可以将文件描述符设置为非阻塞状态,但我暂时将其视为打开

Mat*_*Ife 11

是的,这是检查套接字是否为非阻塞的有效方法。

非阻塞套接字的值为 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
Run Code Online (Sandbox Code Playgroud)

所以,现在你知道怎么做了,我必须指出你的开发人员做错了。如果非阻塞套接字是他们想要使用的东西,那很好——但是他们应该epoll(2)在套接字上设置一个并阻塞轮询。

该程序从产生的非阻塞套接字上一无所获——事实上,结果更糟,因为几乎所有的系统调用都是一个抢占点,内核无论如何都可以在这里切换你。read(2)EAGAIN

该开发人员正在浪费可用于空闲线程的电源和 CPU 周期,并且实际上并没有从他/她这样做中获得任何好处。

如果开发人员想要“缓存线”友好,请将他的任务固定到特定的 CPU 并完成它。