如何在Linux中将进程状态从睡眠改为运行?
我有一个Python程序,需要扫描一些大的日志文件,以提取有用的信息。
在这个程序中,为了更好地利用服务器的计算资源(这台服务器运行的是Ubuntu 12.04 LTS,拥有64个核心和96GB内存),我创建了一个大小为10的进程池,并将任务分配给这些池中的工作进程。每个任务会从几个大文件中读取数据(每个文件大约50GB,总共20个文件),使用file.readlines()
来读取,然后逐行分析这些数据,找出有用的信息,并把结果保存在一个字典里。所有文件扫描和分析完成后,结果字典会被写入磁盘。此外,整个脚本中没有明确调用gc.collect()
。
我使用root账户在服务器上启动了这个程序,最开始这些进程运行得很好:每个进程大约占用3.8GB内存,所以总共占用了40GB。
但是过了几个小时,其他用户启动了另一个消耗内存的程序(同样使用root账户),这个程序几乎占用了所有的内存(99%的总内存),后来这个程序被CTRL-Z
中断,并通过killall -9 process_name
命令被杀掉。
然而,在这之后,我发现我的大部分池工作进程的状态变成了S,CPU使用率降到了0。根据top
的说明:
The status of the task which can be one of:
'D' = uninterruptible sleep,
'R' = running,
'S' = sleeping,
'T' = traced or stopped,
'Z' = zombie
我使用ps -axl
命令检查这些进程睡眠的内核函数名称,结果发现这些池工作进程在_fastMutex
上睡眠。
这种情况持续了很长时间(进程状态现在仍然是S),我不想重启我的进程重新扫描所有文件,我该如何将这些进程的状态从睡眠改为运行呢?
1 个回答
“睡眠状态”表示这些进程在等待某些事情发生;要让它们醒来,就得满足它们所等待的条件(通常是互斥锁在起作用,而不是条件本身)。提到内存消耗,可能意味着一些进程至少部分被换出内存,这种情况下它们会在等待交换器;不过,这样会导致不可中断的睡眠状态D,而不是S。
处于可中断睡眠状态的系统调用可以被信号打断,比如警报、终止、停止或继续。不过,大多数信号会导致程序中止。只有“继续”和“忽略”这两个信号通常是安全的,它们不会改变程序的执行流程;所以程序会再次在同样的条件下继续“睡觉”。
你的进程处于S状态,很可能是因为它们真的在等待外部输入。由于我们对你的程序了解不多,只知道它加载了很多数据,我无法告诉你具体在哪里发生。
关于你描述的程序:“每个任务从几个大文件中读取数据...使用file.readlines(),然后逐行分析。”这种做法效率不高;如果你只是逐行扫描,最好一开始就遍历文件对象(一次读取一行)。如果你是随机顺序读取文本行,linecache会对你有帮助。使用mmap可以避免从磁盘缓冲区复制数据。具体使用哪种方法最好,取决于你的数据结构和算法。
当你说“我的大部分工作进程状态已变为S”时,我怀疑其他工作进程才是重点。也许那些处于睡眠状态的进程只是等待被换出的进程返回。