Linux内核之进程管理

来源:互联网 发布:php用files上传照片 编辑:程序博客网 时间:2024/05/16 16:07

一、Linux进程管理基础

1.1 进程的概念

  进程:处于执行期的程序已经相关资源的总称。相关资源如:打开的文件、挂起的信号、内核内部数据、处理器状态等。

1.2 线程

  线程是执行线程的简称,是在进程中活动的对象。每个线程都拥有独立的计数器、进程栈、和一组进程寄存器。在Linux系统中,内核调度的是线程,而不是进程,Linux系统的线程和进程不做特别区分,对Linux而言,线程不过是一种特殊的进程。
  现代操作系统中,进程提供两种虚拟机制:虚拟内存和虚拟处理器。线程(这里指同一个进程的线程)之间可以共享虚拟内存,但每个线程都拥有各自的虚拟处理器。

1.3 进程创建过程

  父进程调用fork(),产生新的进程——子进程。fork()函数通过复制一个现有进程来创建一个全新的子进程。 fork()系统调用从内核返回两次:第一次是回到父进程;另一次回到新产生的子进程。
  创建后,调用exec()函数就可以创建新的地址空间,并把新的程序载入到这个地址空间中去。
  最后,程序通过调用exit()函数退出执行

1.4 进程描述符

  内核将进程放在任务队列中,这个任务队列实际上是一个双向链表;链表中的每个项(实际上就是任务/进程)都是类型为task_struct(被称为进程描述符)的结构。
  进程描述符是一个结构体,包含打开的文件、进程地址空间、PID、挂起的信号、进程的状态等信息。
  内核通过PID来标识每个进程,PID实际上是一个int类型的数,默认最大值为32768。这个值实际上限定了系统进程的最大数目。对于一个大型服务器来说,可能需要运行更多的进程,这时候可以通过修改内核参数来改变这个值。该参数存放在/proc/sys/kernel/pid_max 文件中,可以通过sysctl命令或者/etc/sysctl.cond文件来修改这一参数
  在内核中,访问任务(进程)通常需要获得指向该任务的task_struct指针。实际上内核中大部分处理进程的代码都是直接通过task_struct进行的,这个过程中,通过current宏查找当前正在运行进程的进程描述符的速度是十分重要的。

1.5 进程的5种状态状态

  进程描述符中的state域描述了进程的当前状态。state的域的值必为下面5种中的一种。

  • TASK-RUNNING(R)
      运行。进程正在运行
  • TASK_INTERRUPTIBLE(S)
      可中断。进程处于阻塞状态。
  • TASK_UNINTERRUPUTIBLE(D)
      不可中断。基本上与可中断一致,但是,处于该状态下的进程,就算是接收到信号也不会被唤醒或者开始运行。这一特性十分重要,当我们执行ps或者top命令的时候,看到了一些状态为D的进程,当我们尝试kill这些进程的时候,发现这种进程并不能被杀死。因为这些进程是不会相响应任何信号的。
  • _TASK_TRACED(T)
      被其他进程跟踪的进程。例如通过ptrace对调试程序进行跟踪。
  • _TASK_STOPPED(T)
      停止。进程停止运行。这种进程既没有运行也不会投入运行

备注:在如ps,top等进程管理命令中,_TASK_TRACED和_TASK_STOPPED状态码同为T。在ps和top等命令中*还可以看到Z状态码,这表示的是僵尸进程。我在翻阅《Linux内核设计与实现》一书时,在进程描述符的state域中,书中并没有将僵尸进程单独列为一个状态。按我的理解,僵尸进程应该是状态转换失败而产生的不良结果,也是一种状态,但是没有在state域中表现。

  • TASK_DEAD - EXIT_ZOMBIE(Z)
      僵尸进程。所谓僵尸进程就是父进程在子进程之前退出,正常情况,子进程必须要找到一个新的父进程作为父进程(如果没有就用init进程作为父进程)。但是,由于某些原因,子进程找不到新的父进程,成为了一个僵尸进程而处于僵死状态,是能白白消耗内存。工作环境中,发现Z进程,必须直接kill。以免拖垮系统

备注:以上的R,S,T,D,Z是上述状态的简写,在top和ps等命令中可以看到

1.6 进程上下文

  CPU运行于两种工作模式,分别是:内核空间和用户空间。正是因为工作模式的不一样,才有了上下文这个概念。当一个程序通过系统调用或者触发了某个异常,这个程序就会陷入内核空间了。此时,由内核代表进程执行运行于内核空间并处于进程上下文中。我们知道,一个程序在运行的时候是需要很多变量的,如果变量不传入内核,当我的进程从用户空间陷入到内核空间后,这个程序就不完整啊,还怎么执行了?所以,用户空间的进程要将寄存器、参数等也传递给内核,内核也要将这些数据保存,以便系统调用结束后,程序回到用户空间继续执行。
  说了这么多,那么什么是上下文呢?当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去
  日常工作中,我们可以使用vmstat查看进程上下文切换带来的影响,看下这个切换是否影响了系统性能。vmstat的用户我将在后面的文章中说明。

1.7 进程上下文切换

  上下文切换就是一个可执行进程切换到另一个可执行进程。切换过程中,需要做到虚拟内存从上一个进程映射到新的进程中;从上个进程的处理器状态切换到新进程的处理器状态,包括:保存、恢复栈信息和寄存器信息,还有其他任何与体系结构相关的状态信息,都必须以每个进程为对象进行管理和保存。

二、进程管理命令

  • ps
ps -eo state,uid,pid,ppid,rtprio,time,comm
  • pstree
  • top
  • htop
  • kill
  • killall
  • vmstat
  • nice
  • renice
  • ulimit
  • ipcs

这些命令不在这里做详解,我会在Linux性能分析系列文章中提到。其实上面的vmstat不算是管理,但是可以使用vmstat查看进程的上下文切换,所以我也把他算在里面了,当然还有一些其他的命令我可能还不知道的….

0 0