Linux进程状态

发布时间 2023-12-16 11:04:05作者: 王景迁

进程状态

top里面S列表示进程状态。

R

正在运行或者等待运行(Running或Runnable),进程在CPU的就绪队列中。

D

硬件交互导致的不可中断睡眠状态(Uninterruptible Sleep),进程正在与硬件交互。 

Z

僵尸进程(Zombie),虽然进程已经结束,但是父进程没有回收它的资源。父进程回收它的资源后会消亡;或者父进程退出后,init进程回收后也会消亡。

S

可中断睡眠状态(Interruptible Sleep),进程因等待而挂起,唤醒后进入R状态。

I

不可中断睡眠的空闲状态(Idle)。D状态进程会使平均负载升高,I状态进程不会。

T

停止状态(stopped),不响应请求,发送SIGSTOP或者SIGTSTP信号来停止进程,发送SIGCONT信号让进程继续运行。其中,SIGSTOP和SIGTSTP信号区别在于,SIGSTOP信号不能捕获。

不可中断进程和僵尸进程案例

代码路径是https://github.com/feiskyer/linux-perf-examples/tree/master/high-iowait-process。
cd linux-perf-examples/high-iowait-process
构建镜像:make build
本地机器:docker run --privileged --name=app -itd feisky/app:iowait

执行top

根据Tasks这一行,有4个正在运行的进程,220个僵尸进程,而且僵尸进程的数量还在不断增加,说明有子进程退出时父进程没清理对应的资源。

通过ps aux | grep Z来寻找僵尸进程。

通过pstree -aps | grep 3381来寻找僵尸进程的父进程。

确认app应用代码是否存在问题,找到子进程的创建和清理位置

int status = 0;
for (;;) {
    for (int i = 0; i < 2; i++) {
        if(fork()== 0) {
            sub_process();
        }
    }
    sleep(5);
}

while(wait(&status)>0);

wait函数等待子进程结束没被调用到,把它挪到for循环里面。

int i = 0;
for (;;)
{
    for (i = 0; i < 2; i++)
    {
        if (fork() == 0)
        {
            sub_process(disk, buffer_size, buffer_count);
        }
    }

    while (wait(&status) > 0);
    sleep(5);
}

子进程结束运行后,如果父进程没有调用wait或者waitpid来获取子进程的状态,内核无法释放内存中的子进程PCB,那么子进程成为僵尸进程。
fork出来的子进程和父进程同名,prctl设置的进程名只有在子进程死后或者变成僵尸进程时才显示。

参考资料

 Linux 性能优化实战