linux的进程状态与管理

进程状态:

1)进程的状态的概述:

1.1)Running(R),运行或将要运行
1.2)Interruptible(S),被阻断而等待一个事件,可能会被一个信号激活
1.3)Uninterruptible(D),被阻断而等待一个事件,不会被信号激活
1.4)Stopped(T),由于任务的控制或者外部的追踪而被终止,比如:strace
1.5)Zombie(Z),僵死,但是它的父进程尚未调用wait函数.
1.6)Deal(X),这个永远看不见

在内核源代码中的定义如下:

=====================================================
/usr/src/linux/fs/proc/array.c

static const char *task_state_array[] = {
        "R (running)",          /*  0 */
        "S (sleeping)",         /*  1 */
        "D (disk sleep)",       /*  2 */
        "T (stopped)",          /*  4 */
        "T (tracing stop)",     /*  8 */
        "Z (zombie)",           /* 16 */
        "X (dead)"              /* 32 */
};
=====================================================

在ps命令的帮助中定义如下:

PROCESS STATE CODES
       Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to
       describe the state of a process.
       D    Uninterruptible sleep (usually IO)
       R    Running or runnable (on run queue)
       S    Interruptible sleep (waiting for an event to complete)
       T    Stopped, either by a job control signal or because it is being traced.
       W    paging (not valid since the 2.6.xx kernel)
       X    dead (should never be seen)
       Z    Defunct ("zombie") process, terminated but not reaped by its parent.

For BSD formats and when the stat keyword is used, additional characters may be displayed:
       <    high-priority (not nice to other users)
       N    low-priority (nice to other users)
       L    has pages locked into memory (for real-time and custom IO)
       s    is a session leader
       l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
       +    is in the foreground process group
======================================================

关于D和Z一段有趣的解释:
 
    有一类垃圾却并非这么容易打扫,那就是我们常见的状态为 D (Uninterruptible sleep) ,以及状态为 Z (Zombie) 的垃圾进程。这些垃圾进程要么是求而不得,像怨妇一般等待资源(D),要么是僵而不死,像冤魂一样等待超度(Z),它们在 CPU run_queue 里滞留不去,把 Load Average 弄的老高老高,没看过我前一篇blog的国际友人还以为这儿民怨沸腾又出了什么大事呢。怎么办?开枪!kill -9!看你们走是不走。但这两种垃圾进程偏偏是刀枪不入的,不管换哪种枪法都杀不掉它们。无奈,只好reboot,像剿灭禽流感那样不分青红皂白地一律扑杀!
 
    怨妇 D,往往是由于 I/O 资源得不到满足,而引发等待,在内核源码 fs/proc/array.c 里,其文字定义为“ "D (disk sleep)", /* 2 */ ”(由此可知 D 原是Disk的打头字母),对应着 include/linux/sched.h 里的“ #define TASK_UNINTERRUPTIBLE 2 ”。举个例子,当 NFS 服务端关闭之时,若未事先 umount 相关目录,在 NFS 客户端执行 df 就会挂住整个登录会话,按 Ctrl+C 、Ctrl+Z 都无济于事。断开连接再登录,执行 ps axf 则看到刚才的 df 进程状态位已变成了 D ,kill -9 无法杀灭。正确的处理方式,是马上恢复 NFS 服务端,再度提供服务,刚才挂起的 df 进程发现了其苦苦等待的资源,便完成任务,自动消亡。若 NFS 服务端无法恢复服务,在 reboot 之前也应将 /etc/mtab 里的相关 NFS mount 项删除,以免 reboot 过程例行调用 netfs stop 时再次发生等待资源,导致系统重启过程挂起。

  冤魂 Z 之所以杀不死,是因为它已经死了,否则怎么叫 Zombie(僵尸)呢?冤魂不散,自然是生前有结未解之故。在UNIX/Linux中,每个进程都有一个父进程,进程号叫PID(Process ID),相应地,父进程号就叫PPID(Parent PID)。当进程死亡时,它会自动关闭已打开的文件,舍弃已占用的内存、交换空间等等系统资源,然后向其父进程返回一个退出状态值,报告死讯。如果程序有 bug,就会在这最后一步出问题。儿子说我死了,老子却没听见,没有及时收棺入殓,儿子便成了僵尸。在UNIX/Linux中消灭僵尸的手段比较残忍,执行 ps axjf 找出僵尸进程的父进程号(PPID,第一列),先杀其父,然后再由进程天子 init(其PID为1,PPID为0)来一起收拾父子僵尸,超度亡魂,往生极乐。注意,子进程变成僵尸只是碍眼而已,并不碍事,如果僵尸的父进程当前有要务在身,则千万不可贸然杀之。

2)分析不可被中断的睡眠进程:

2.1)重现:

终端1)

vi test.c
#include <unistd.h>

void main() { 
if (!vfork()) sleep(100);

gcc test.c -o test

./test

终端2)
ps aux|grep test
root     19884  0.0  0.0   3640   360 pts/0    D+   16:38   0:00 ./test
root     19885  0.0  0.0   3640   360 pts/0    S+   16:38   0:00 ./test

2.2)分析:
系统进入这种不可中断是很少发生的,即使发生也是一个短暂的状态,引起这种状态的发生一般是驱动程序.
例如:驱动程序可能正在特殊的设备上等待通过检测的响应,但又要保证自己不在可中断睡眠状态(S)被中断.所以驱动程序会把进程切换到不可中断的睡眠状态,直到硬件已返回到已知状态.

可以通过访问一个慢设备来观察不可中断的睡眠状态,比如CDROM这样的设备
例如:
dd if=/dev/cdrom f=/dev/null &

进程在一个不可中断的状态是十分危险的,你不能用kill -9杀掉它
例如:
一个有问题的驱动程序访问一个有问题的设备,设备不给驱动程序响应,驱动程序永远得不到响应,而又永远等待响应.

3)分析被跟踪或被停止的进程状态(T)

3.1)重现被跟踪时的状态:

终端1)
strace top

终端2)
ps auxf|grep top
root       980  9.4  0.0  1716  608 pts/0    S    00:31   0:12  |       \_ strace top
root       981  3.7  0.1 10084 7076 pts/0    T    00:31   0:05  |           \_ top

在用strace跟踪top执行的时候,top进程为T的状态

3.2)重现被停止的进程状态:

停止进程有三种手段:
3.2.1)发送SIGTSTP信停止进程.
-SIGTSTP的信号相当于CTRL+Z的组合键来终止正在前台运行的进程.

终端1)
vi /etc/passwd

终端2)
kill -SIGTSTP 12029

查看进程状态:
ps auxf

root     10297  0.0  1.0   5124  2696 pts/0    Ss+  Dec16   0:00      \_ -bash
root     12029  0.0  0.8   5348  2200 pts/0    T    05:15   0:00      |   \_ vi test.c

终端1)
查看放到后台的作业
jobs
[1]+  Stopped                 vi test.c

用fg将作业切换到前台
fg

3.2.2)进程自已终止自己,标准输入引起进程停止

一个终端利用常规的后台和前台进程管理进程,一个终端有且只有一个前台进程,只有这个进程可以接受键盘的输入,其它任何开始于终端的进程都被认为是后台进程,但是当后台进程试图从标准输入读取数据时,终端将发送一个SIGTTIN终端它,因为这里只有一个输入设备键盘,只能用于前台进程.
这里的前后台进程概念仅限于终端的范围.

SIGTTIN 当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN 信号. 缺省时这些进程会停止执行.

终端1)

尝试在后台运行read命令,因为后台进程不能从终端获取标准输入,所以进程将会收到信号SIGTTIN,使进程进入停止状态.
read x &
[1] 12057

[1]+  Stopped                 read x

终端2)
jobs
[1]+  Stopped                 read x
查看进程,12057这个PID就是read x&,现在看到是-bash,它的状态已经是T了
ps aux
root     12057  0.0  0.5   5124  1476 pts/0    T    05:26   0:00 -bash

用SIGCONT来唤醒
kill -SIGCONT 12057

终端1)
输入回车后,12057的进程依然会进入停止状态,也就是阻塞,只有会放到前台后,它才能完成输入.
fg
read x
hello

3.2.3)进程自已终止自己,标准输出引起进程停止

终端有一个tostop(终端输出终止)设置,在大多数系统里默认是关闭.
当是关闭的状态时,后台进程可以随时在终端写内容,如果是开启状态时,后台进程向标准输出写数据时就会被终止.

开启tostop
stty tostop

向标准输出写数据,被停止了
echo hello world &
[1] 12125

[1]+  Stopped                 echo hello world

jobs
[1]+  Stopped                 echo hello world

关闭tostop
stty -tostop

jobs
[1]+  Stopped                 echo hello world

向标准输出写数据恢复正常了
fg
echo hello world
hello world

4)分析进程的可中断睡眠态与运行态

编写一个小程序测试睡眠态与运行态之后的转换 :
=====================================================
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>

void
run_status(void)
{
    double pi = M_PI;
    double pisqrt;
    long i;
   
    for (i=0; i<100000000; ++i){
    pisqrt = sqrt(pi);
    }
}

int
main (void)
{
    run_status();    
    sleep(10);
    run_status();

exit(EXIT_SUCCESS);
}
======================================================
编译链接后:
gcc -Wall -o pisqrt a.c -lm

终端1)
监控pisqrt进程
watch -n 1 "ps aux|grep pisqrt|grep -v ps|awk ‘{print $2}‘|sort -k 8"

终端2)
strace ./pisqrt
显示如下:
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200X\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1572440, ...}) = 0
old_mmap(NULL, 1279916, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x49e000
old_mmap(0x5d1000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x132000) = 0x5d1000
old_mmap(0x5d4000, 10156, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x5d4000
close(3)                                = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75e3a60, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb75e4000, 75579)               = 0

此时切换到终端1看pisqrt进程状态,此时为R状态:
root      3792 99.9  0.0  1516  268 pts/2    R    02:40   0:01 ./pisqrt     
root      3801  0.0  0.0  3700  672 pts/1    S    02:40   0:00 grep pisqrt
root      3791  1.0  0.0  1728  564 pts/2    S    02:40   0:00 strace ./pisqr

之后pisqrt进程进入S状态,因为执行了sleep(10)函数,10秒之后pisqrt再次进入R状态.最终退出.

分析:
pisqrt占用CPU时间片时状态为R,而在调用sleep函数后为S,系统大多数进程状态都为S,比如APACHE和ORACLE,
而处于S状态不一定是调用了sleep函数,因为IO也会让进程处于睡眠态.
而我们可以启动多个pisqrt程序,这时在系统中会有多个R状态的进程.也就是说CPU个各数与R进程是没有直接关联的.

5)分析进程的僵死态(Z)

当一个进程退出时,它并不是完全消失,而是等到它的父进程发出wait系统调用才会完全消失,除非父进程发出wait系统调用终止进程,
否则该进程将一直处于所谓的僵死状态,等待它的父进程终止它.如果父进程终止了运行而没有撤销子进程,那么这些进程将被进程init收养.
init进程定期调用wait来收养这些未被撤消的进程.

先制造一段僵尸程序,如下:
=============================
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int
main (){
    if(!fork()){
    printf("child pid=%d\n", getpid());
    exit(5);
}
    sleep(20);
    printf("parent pid=%d\n", getpid());
    exit(EXIT_SUCCESS);
}
===========================================
编译
gcc -Wall defunct.c -o defunct

终端1:
watch -n 1 "ps auxf|grep defunct|grep -v ps|grep -v grep|awk ‘{print $2}‘|sort -k 8"

终端2:
执行./defunct

查看终端1:
root      7280  0.0  0.0  1380  240 pts/2    S    03:05   0:00  |       \_ ./defunct
root      7281  0.0  0.0     0    0 pts/2    Z    03:05   0:00  |           \_ [defunct <defunct>]

20秒后查看终端2:
child pid=7281
parent pid=7280

关于信号集的描述:/usr/include/bits/signum.h

#define SIGCLD          SIGCHLD /* Same as SIGCHLD (System V).  */
#define SIGCHLD         17      /* Child status has changed (POSIX).  */

在上面程序的基础上加入wait函数即可将SIGCHLD信号回收

修改后的程序如下:
=================================
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int
main (){
    int status,i;
    if(!fork()){
    printf("child pid=%d\n", getpid());
    exit(5);
}
    wait(&status);
    i = WEXITSTATUS(status);
    sleep(20);
    printf("parent pid=%d,child process exit/status=%d\n", getpid(),i);
    exit(EXIT_SUCCESS);
}
==========================================

6)最后的进程X (dead)
指死掉的进程

最后4种附加的状态....
W状态:不驻留内存
<状态:nice小于0
N状态:nice大于0
L状态:有锁住的页面

这部分在ps的源代码(output.c)有描述:
===================================
static int
pr_stat(void)
{
        int end = 0;
        outbuf[end++] = pp->state;
        if (pp->rss == 0 && pp->state != ‘Z‘)
                outbuf[end++] = ‘W‘;
        if (pp->nice < 0)
                outbuf[end++] = ‘<‘;
        if (pp->nice > 0)
                outbuf[end++] = ‘N‘;
        if (pp->vm_lock)
                outbuf[end++] = ‘L‘;
        outbuf[end] = ‘\0‘;
        return end;
}
=====================================

进程管理:

fg、bg、jobs、&、ctrl+z命令

一、 &
加在一个命令的最后,可以把这个命令放到后台执行 ,如sh start.sh &

二、ctrl + z
可以将一个正在前台执行的命令放到后台,并且处于暂停状态,不可执行。

三、jobs:查看当前有多少在后台运行

jobs -l选项可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated,但是如果任务被终止了(kill)

四、fg:将后台中的命令调至前台运行
如果后台中有多个命令,可以用 fg %jobnumber将选中的命令调出,%jobnumber是通过jobs命令查到的后台正在执行的命令的序号,而不是pid

五、bg:将一个在后台暂停的命令,变成继续执行 (后台执行
如果后台中有多个命令,可以用bg %jobnumber将选中的命令调出,%jobnumber是通过jobs命令查到的后台正在执行的命令的序号(不是pid)
将任务转移到后台运行:先ctrl + z;再bg,这样进程就被移到后台运行,终端还能继续接受命令。

当前任务
如果后台的任务号有2个,[1],[2];如果当第一个后台任务顺利执行完毕,第二个后台任务还在执行中时,当前任务便会自动变成后台任务号码“[2]” 的后台任务。所以可以得出一点,即当前任务是会变动的。当用户输入“fg”、“bg”和“stop”等命令时,如果不加任何引号,则所变动的均是当前任务

进程的终止
后台进程的终止:
方法一:
通过jobs命令查看job号(假设为num),然后执行kill %num

方法二:
通过ps命令查看job的进程号(PID,假设为pid),然后执行kill pid

前台进程的终止:
ctrl+c

kill的其他作用
kill除了可以终止进程,还能给进程发送其它信号,使用kill -l 可以察看kill支持的信号。
SIGTERM是不带参数时kill发送的信号,意思是要进程终止运行,但执行与否还得看进程是否支持。如果进程还没有终止,可以使用kill -SIGKILL pid,这是由内核来终止进程,进程不能监听这个信号。

后台进程的挂起:
在redhat中,不存在stop命令,可通过执行命令kill -stop PID,将进程挂起;

当要重新执行当前被挂起的任务时,通过bg %num 即可将挂起的job的状态由stopped改为running,仍在后台执行;当需要改为在前台执行时,执行命令fg %num即可。

前台进程的挂起:
ctrl+Z

linux的进程状态与管理

时间: 2024-10-13 22:52:58

linux的进程状态与管理的相关文章

Linux进程查看与管理、作业控制、网络客户端工具

写在前面: 博客书写牢记5W1H法则:What,Why,When,Where,Who,How. 本篇主要内容: ● 基础概念介绍 进程优先级 进程状态 ● 进程查看与管理命令     pstree     ps     pgrep/pkill     pidof     top     htop     vmstat     pmap     glances     dstat     kill     killall ● linux作业控制     nice     renice ● 网络客户

Linux进程查看及管理的工具

Linux进程查看及管理的工具:pstree, ps, pidof, pgrep, top, htop, glance, pmap, vmstat, dstat, kill, pkill, job, bg, fg, nohup 1.pstree命令:    pstree - display a tree of processes    [[email protected] ~]# pstreeinit─┬─agetty     ├─auditd───{auditd}     ├─crond   

20150917 Linux进程查看与管理以及作业管理

第一.基础知识 MBR引导--内核--内核程序-->协调其它程序 一般内核运行在硬件之上,各应用也在硬件之前 1)OS的基本功能:文件系统.网络功能.进程管理.内存管理.驱动程序.安全功能 以上为通用目的设置的程序., 程序=指令+数据, 程序运行在内存当中.这个内存由物理内存映射逻辑空间 左则表示二个框分别表示指令和数据.物理内存划分固定大小的页框称为pageframe. 右则下面的方框表示物理内存.每个进程在右则上面的方框中,这部分为假的内存 空间称为线性地址空间. 2)CPU指令:  四个

9-17 linux进程查看和管理

Linux进程查看与管理 OS的基本功能:文件系统.网络功能.进程管理.内存管理.驱动程序.安全功能 程序=指令+数据 CPU:  特权指令  普通指令 程序执行环境:  内核模式:运行内核级指令  用户模式:运行普通指令 应用程序:   运行普通指令:直接运行于CPU   运行特权指令:通过system call 内存:8bits, 1byte  32bits, 2^32, 0-2^32-1, 2^10*2^10*2^10*2^2 bytes = 2^10*2^10*2^2 kilo byte

Linux学习之进程管理(十九)

Linux学习之进程管理 进程查看 查看系统中所有进程,使用BSD操作系统的格式 语法:ps aux 选项: a:显示所有前台进程 x:显示所有后台进程 u:显示这个进程是由哪个用户产生的 语法:ps -le 查看系统中所有进程,使用Linux标准命令格式 选项 l:显示详细信息 e:显示所有进程 USER:该进程是由哪个用户产生的 PID:进程的ID号 %CPU:该进程占用CPU资源的百分比,占用越高,进程越消耗资源. %MEM:该进程占用物理内存的百分比,占用越高,进程越消耗资源. VSZ:

Linux系统进程查看及管理工具

Linux系统进程查看及管理工具 ps命令ps:report a snapshot of the current processes.ps [options]:选项有三种风格:1 UNIX options, which may be grouped and must be preceded by a dash.2 BSD options, which may be grouped and must not be used with a dash.3 GNU long options, which

linux下的进程管理(进程的基本了解及查看pstree,ps,pgrep命令)

Linux下的进程管理 1.什么是进程?程序是静态的文件进程是运行中的程序的一个副本进程存在生命周期(准备期,运行期,终止期)2.进程状态 状态 定义 R(TASK_RUNNING) . 可执行状态(RUNNING,READY)running:正在被处理 ready: 在排队, cpu处理进程个数有限 S(TASK_INTERRUPTIBLE) 可唤醒状态 :在cpu上使用的时间超时,此时被打入休眠状态,随着程序的调用会被唤醒 D(TASK_UNINTERRUPTIBLE) 不可唤醒状态 T(T

linux用户和文件目录管理

Linux用户及权限管理 用户管理 多用户多任务的操作系统 用户类型 管理员用户 root 普通用户 系统用户/程序用户 用户相关的文件: /etc/passwd 用户信息 格式: 用户名:x:UID:GID:说明信息:SHELL UID: 1000---60000 0---999 系统用户 SHELL: /bin/bash 默认 /sbin/nologin 系统用户 /etc/shadow 用户密码信息 用户: 基本组 附加组 用户userA -----> 用户组userA;    caiwu

Linux基础之磁盘管理

 Linux基础之磁盘管理         关于Linux中磁盘管理我们应该从以下四个方面入手,去了解和学习磁盘管理的知识. 第一点 磁盘的结构--硬盘         硬盘的参数 结构:磁盘的盘片,磁头,马达(机械键盘) 类型:固态硬盘(SSB)和机械硬盘 接口:早期的IDE接口,现在的SATA,SCSI,SAS 还有容量,转速,传输速度,缓存等. 硬盘存储术语 head: 磁头 track: 磁道 cylinder: 柱面 secotr: 扇区  512bytes(字节) 第二点 磁盘的分区