美文网首页
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