美文网首页
30 Linux 进程

30 Linux 进程

作者: StarShift | 来源:发表于2016-10-21 16:36 被阅读154次

    看一眼进程

    我们可以使用$ps命令来查询正在运行的进程,比如$ps -eo pid,comm,cmd,下图为执行结果:(-e表示列出全部进程,-o pid,comm,cmd表示我们需要PID,COMMAND,CMD信息)

    Paste_Image.png

    每一行代表了一个进程。每一行又分为三列。第一列PID(process IDentity)是一个整数,每一个进程都有一个唯一的PID来代表自己的身份,进程也可以根据PID来识别其他的进程。第二列COMMAND是这个进程的简称。第三列CMD是进程所对应的程序以及运行时所带的参数。
    (第三列有一些由中括号[]括起来的。它们是内核的一部分功能,被打扮成进程的样子以方便操作系统管理。我们不必考虑它们。)

    我们看第一行,PID为1,名字为init。这个进程是执行/bin/init这一文件(程序)生成的。当Linux启动的时候,init是系统创建的第一个进程,这一进程会一直存在,直到我们关闭计算机。

    如何创建一个进程

    实际上,当计算机开机的时候,内核(kernel)只建立了一个init进程。Linux内核并不提供直接建立新进程的系统调用。剩下的所有进程都是init进程通过fork机制建立的。
    新的进程要通过老的进程复制自身得到,这就是fork。fork是一个系统调用。进程存活于内存中。每个进程都在内存中分配有属于自己的一片空间 (address space)。
    当进程fork的时候,Linux在内存中开辟出一片新的内存空间给新的进程,并将老的进程空间中的内容复制到新的空间中,此后两个进程同时运行。
    老进程成为新进程的父进程(parent process),而相应的,新进程就是老的进程的子进程(child process)。一个进程除了有一个PID之外,还会有一个PPID(parent PID)来存储的父进程PID。如果我们循着PPID不断向上追溯的话,总会发现其源头是init进程。所以说,所有的进程也构成一个以init为根的树状结构。

    如下,我们查询当前shell下的进程:

    root@vamei:~# ps -o pid,ppid,cmd 
    PID PPID CMD
    16935 3101 sudo -i
    16939 16935 -bash
    23774 16939 ps -o pid,ppid,cmd
    

    我们可以看到,第二个进程bash是第一个进程sudo的子进程,而第三个进程ps是第二个进程的子进程。

    还可以用$pstree命令来显示整个进程树:

    init─┬─NetworkManager─┬─dhclient
         │                └─2*[{NetworkManager}]
         ├─accounts-daemon───{accounts-daemon}
         ├─acpid
         ├─apache2─┬─apache2
         │         └─2*[apache2───26*[{apache2}]]
         ├─at-spi-bus-laun───2*[{at-spi-bus-laun}]
         ├─atd
         ├─avahi-daemon───avahi-daemon
         ├─bluetoothd
         ├─colord───2*[{colord}]
         ├─console-kit-dae───64*[{console-kit-dae}]
         ├─cron
         ├─cupsd───2*[dbus]
         ├─2*[dbus-daemon]
         ├─dbus-launch
         ├─dconf-service───2*[{dconf-service}]
         ├─dropbox───15*[{dropbox}]
         ├─firefox───27*[{firefox}]
         ├─gconfd-2
         ├─geoclue-master
         ├─6*[getty]
         ├─gnome-keyring-d───7*[{gnome-keyring-d}]
         ├─gnome-terminal─┬─bash
         │                ├─bash───pstree
         │                ├─gnome-pty-helpe
         │                ├─sh───R───{R}
         │                └─3*[{gnome-terminal}]
    

    进程的状态

    进程又分为以下几种状态:

    1. 运行(正在运行或在运行队列中等待)
    2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
    3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
    4. 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
    5. 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)

    其对应在ps上的相应状态码如下:

    状态 定义
    R running 运行中
    S Interruptible Sleep.等待调用
    D Uninterruptible Sleep.等待磁盘IO
    T Stoped.暂停或者跟踪状态
    X Dead.即将被撤销
    Z Zombie.进程已经结束,仅映像名留存
    W Paging.内存交换
    N 优先级低的进程
    < 优先级高的进程
    s 进程的领导者
    L 锁定状态
    l 多线程状态
    + 前台进程

    平时在查看linux进程状态时,查看最多的三个状态是R S D :

    • R状态,不必多说,R就是running的缩写,即运行中的进程。
    • S 即 sleep进程,休眠进程。其又分为两种:
      1. Interruptible Sleep(可中断睡眠,在ps命令中显示“S”)。处在这种睡眠状态的进程是可以通过给它发送signal来唤醒的,比如发HUP信号给nginx的master进程可以让nginx重新加载配置文件而不需要重新启动nginx进程;
      2. Uninterruptible Sleep(不可中断睡眠,在ps命令中显示“D”)。处在这种状态的进程不接受外来的任何signal,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是“kill”, “kill -9”还是“kill -15”,因为它们压根儿就不受这些信号的支配。
        D 即上面提到的Uninterruptible Sleep ,如果从广义上来分,D状态算是一种特殊的S状态进程。进程为什么会被置于D状态呢?
        D状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如NFS挂载的远程文件系统已经不可访问了。

    前台进程和后台进程

    前台进程

    指一个进程控制着标准输入/输出,在程序运行时,shell被暂时挂起,直到程序运行结束。在这个过程中,用户不能执行其他程序。

    后台进程

    用户不必等待这个任务结束就可以运行其它进程。

    一个终端只能运行一个前台进程,但是可以运行多个后台进程。

    运行后台进程

    可以在命令之后加上一个 & 来讲进程放到后台执行。

    sleep 60 &
    

    但是,放到后台运行的进程仍然会在termital 退出的时候退出。

    如果当前程序已经在前台运行,想把它转到后台运行,可以使用ctr+z将其挂起,然后利用bg命令将其转到后台运行。
    如果需要将一个命令转到前台运行,可以使用命令fg。

    root@ubuntu:~# sleep 60
    ^Z
    [1]+  Stopped                 sleep 60
    root@ubuntu:~# bg
    [1]+ sleep 60 &
    root@ubuntu:~# jobs
    [1]+  Running                 sleep 60 &
    root@ubuntu:~# fg
    sleep 60
    
    

    另外,可以使用jobs查看后台挂起的进程。

    root@ubuntu:~# sleep 111
    ^Z
    [1]+  Stopped                 sleep 111
    root@ubuntu:~# bg
    [1]+ sleep 111 &
    root@ubuntu:~# sleep 112
    ^Z
    [2]+  Stopped                 sleep 112
    root@ubuntu:~# bg
    [2]+ sleep 112 &
    root@ubuntu:~# sleep 113 
    ^Z
    [3]+  Stopped                 sleep 113
    root@ubuntu:~# bg
    [3]+ sleep 113 &
    root@ubuntu:~# jobs
    [1]   Running                 sleep 111 &
    [2]-  Running                 sleep 112 &
    [3]+  Running                 sleep 113 &
    

    使用jobs需要在同一个terminal,在另外一个terminal 是看不到当前的jobs信息的。

    • 第一列表示任务号
    • + 表示当前任务
    • - 表示当前任务之前开始的任务
    root@ubuntu:~# jobs
    root@ubuntu:~# jobs
    

    任务运行结束后,执行状态由running变成done。

    root@ubuntu:~# jobs
    [1]   Done                    sleep 111
    [2]-  Done                    sleep 112
    [3]+  Done                    sleep 113
    

    nohup

    刚刚看到执行的命令在terminal退出之后就退出了,如果希望运行的命令在terminal退出之后不退出,那么可以使用nohup。

    nohup sleep 60 &
    

    进程的nice值和优先级

    在任务队列中的进程不享有相同的优先级,每个进程都有一个指定的nice值(优先级权值),从 -20 到19。

    • 可以使用 nice 命令查看缺省的优先级。
    root@ubuntu:~# nice
    0
    
    • 可以使用 ps -l [pid] 查看指定进程的优先级。
    root@ubuntu:~# ps -l 1831 
    F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY        TIME CMD
    0 S   112   1831      1  0  80   0 - 85927 poll_s ?          0:00 /usr/lib/x86_64-linux-gnu/notify-osd
    

    调整进程的优先级

    可以在进程启动的时候调整进程的优先级,使用命令:nice在进程启动的时候指定进程的优先级,命令格式:

    nice -n 命令 & 
    

    n 是优先级的增量,如果:

    • n 是正数:表示增加nice 的值,也就是降低进程的优先级。
    • n 是负数:表示减少nice 的值,也就是增加进程的优先级。
    • 若为缺省:则是10, 表示增加nice值10 。

    注:
    普通用户只能增加nice值,只有管理员才能降低一个进程的nice值。

    进程运行后调整nice值

    使用renice命令修改已经运行的进程的nice值, 例如:

    renice 5 2673
    

    增加进程2673 的nice值。

    普通用户一旦增加了nice值,就无法恢复到原来的nice值。

    相关文章

      网友评论

          本文标题:30 Linux 进程

          本文链接:https://www.haomeiwen.com/subject/cyjquttx.html