杨立峰 2018-12-10
进程管理在任何操作系统上都是最重要事情。高效的进程管理能够确保应用高效稳定的运 行。 Linux的进程管理方式类似于Unix的进程管理方式,包含进程调度、中断处理、信号、进程优 先级、进程切换、进程状态、进程的内存等等。
进程是在处理器中执行的实例,内核调度各类资源来满足进程的需求。 所有运行在Linux操作系统的进程都被task_struct这个结构体管理,task_struct也被称为进程 描述符。进程描述符包含一个进程运行所需的所有信息,比如进程的id、进程的属性以及构建 进程的资源。
进程信息相关结构
每个进程都有自己生命周期,比如创建、执行、终止和删除。在系统运行过程中,这些阶段 反复执行成千上万次。因此,从性能的角度来看,进程的生命周期十分重要。
一般进程的生命周期
当一个进程创建一个新的进程,创建进程的进程(父进程)使用名为fork()的系统调用。当 fork()被调用的时候,它会为新创建的进程(子进程)获得一个进程描述符,并且设置新的进 程ID。复制父进程的进程描述符给子进程。这时候,不会复制父进程的地址空间,而是父子 进程使用同样的地址空间。
exec()系统调用把新程序复制到子进程的地址空间。由于共享同样的地址空间,写入新进程的 数据会引发页错误的异常。此时,内核给子进程分配新的物理页。
这个延迟的操作叫做Copy On Write。子进程和父进程执行的程序通常不一样,它执行自己的 程序。这个操作避免了不必要的开销,因为,复制整个地址空间是很慢且低效率的,还会消 耗很多的处理器时间和资源。
当程序执行完成,子进程使用exit()系统调用终止。exit()会释放进程的大部分数据结构,并且 把这个终止的消息通知给父进程。这时候,子进程被称为zombie process(僵尸进程)。 直到父进程通过wait()系统调用知悉子进程终止之前,子进程都不会被完全的清除。一旦父进 程知道子进程终止,它会清除子进程的所有数据结构和进程描述符。
线程是单个进程中生成的执行单元。多个线程在同一个进程中并发运行。它们共享内存、地 址空间、打开文件等等资源。还能访问同样的应用数据集。线程也被称为轻量级进程(Light Weight Process)。由于线程间共享资源,线程不能同时改变它们共享的资源。互斥、锁、 序列化等等都是由用户应用程序来实现。
从性能的角度看,创建线程比创建进程更加低消耗,因为创建线程不需要复制资源。另一方 面,从进程和线程在调度上看,他们拥有相似的行为。内核用类似的方法来处理他们。
在当前的Linux实现中,线程由POSIX(Portable Operating System Interface for UNIX,可移 植操作系统接口)的兼容库(pthread)提供。Linux支持多线程。
进程优先级由动态优先级和静态优先级决定,它是决定进程在CPU中执行顺序的数字。优先 级越高的进程被处理器执行的机会越大。
根据进程的行为,内核使用启发式算法决定开启或关闭动态优先级。可以通过nice级别直接修 改进程的静态优先级,拥有越高静态优先级的进程会获得更长的时间片(时间片是进程在处 理器中的执行时间)。
Linux支持的nice级别从19(最低优先级)到-20(最高优先级),默认只是0。只有root身份 的用户才能把进程的nice级别调整为负数(让其具备较高优先级)。
每个进程都有自己的状态,显示进程中当前发生的事情,进程执行时进程状态发生改变。
可能的状态列表如下:
后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下!!