如何在Linux中将进程状态从睡眠改为运行?

2 投票
1 回答
10370 浏览
提问于 2025-04-18 03:22

我有一个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 个回答

4

“睡眠状态”表示这些进程在等待某些事情发生;要让它们醒来,就得满足它们所等待的条件(通常是互斥锁在起作用,而不是条件本身)。提到内存消耗,可能意味着一些进程至少部分被换出内存,这种情况下它们会在等待交换器;不过,这样会导致不可中断的睡眠状态D,而不是S。

处于可中断睡眠状态的系统调用可以被信号打断,比如警报、终止、停止或继续。不过,大多数信号会导致程序中止。只有“继续”和“忽略”这两个信号通常是安全的,它们不会改变程序的执行流程;所以程序会再次在同样的条件下继续“睡觉”。

你的进程处于S状态,很可能是因为它们真的在等待外部输入。由于我们对你的程序了解不多,只知道它加载了很多数据,我无法告诉你具体在哪里发生。

关于你描述的程序:“每个任务从几个大文件中读取数据...使用file.readlines(),然后逐行分析。”这种做法效率不高;如果你只是逐行扫描,最好一开始就遍历文件对象(一次读取一行)。如果你是随机顺序读取文本行,linecache会对你有帮助。使用mmap可以避免从磁盘缓冲区复制数据。具体使用哪种方法最好,取决于你的数据结构和算法。

当你说“我的大部分工作进程状态已变为S”时,我怀疑其他工作进程才是重点。也许那些处于睡眠状态的进程只是等待被换出的进程返回。

撰写回答