(1)Linux性能调优之Linux进程管理

1、背景

玩过一段时间Linux后,你们是否发现Linux也就是一个操做系统而已,和windows是相似的,只不过是windows拥有图形化界面,而Linux大部分状况下只是个黑黑的窗口。windows多用于我的,而Linux由于出色的性能而多用于服务器。算法

服务器不是智能的,Linux也不是智能的,因此须要运维人员经过调试,将服务器的硬件和Linux的特性结合起来,从而达到性能最大输出,这就是我理解的Linux性能调优。下面展现的是一张服务器和Linux系统结合的概览图:windows

服务器和Linux系统结合的概览图

2、基础知识

调优不是说调就调的,咱们要先了解Linux是如何处理任务以及与硬件资源进行交互的。性能调优须要在深入理解硬件资源、操做系统和应用程序的基础上进行。下面说一下在Linux中和性能关系最密切的几个部分。数组

3、Linux进程管理

  • 3.1 什么是进程?

进程是在处理器中执行的实例,Linux内核调度各种资源来知足进程的需求。个人理解是,应用程序是存储硬盘上的数据,经过程序入口将应用程序装载到内存运行起来后就生成了一个进程(运行中的程序)。进程会使用各类资源,如CPU,键盘鼠标,处理器,硬盘等,而这些工做由Linux内核调度,以知足各个进程间的协同,竞争等。缓存

Linux的进程管理方式相似于Unix的进程管理方式,包含进程调度、中断处理、信号、进程优先级、进程切换、进程状态、进程的内存等等bash

全部运行在Linux操做系统的进程都被task_struct这个结构体管理,task_struct也被称为进程描述符。进程描述符包含一个进程运行所需的全部信息,好比进程的id、进程的属性以及构建进程的资源。服务器

下图展现了进程信息相关结构的概览:网络

  • 3.2 进程的生命周期

每一个进程都有本身生命周期,好比建立、执行、终止和删除。在系统运行过程当中,这些阶段反复执行成千上万次。所以,从性能的角度来看,进程的生命周期十分重要。数据结构

下图展现了通常进程的生命周期:多线程

当一个进程建立一个新的进程,建立进程的进程(父进程)使用名为fork()的系统调用。当fork()被调用的时候,它会为新建立的进程(子进程)得到一个进程描述符,而且设置新的进程ID。复制父进程的进程描述符给子进程。这时候,不会复制父进程的地址空间,而是父子进程使用一样的地址空间。架构

exec()系统调用把新程序复制到子进程的地址空间。因为共享一样的地址空间,写入新进程的数据会引起页错误的异常。此时,内核给子进程分配新的物理页。这个延迟的操做叫作Copy On Write。子进程和父进程执行的程序一般不同,它执行本身的程序。这个操做避免了没必要要的开销,由于,复制整个地址空间是很慢且低效率的,还会消耗不少的处理器时间和资源。

当程序执行完成,子进程使用exit()系统调用终止。exit()会释放进程的大部分数据结构,而且把这个终止的消息通知给父进程。这时候,子进程被称为zombie process(僵尸进程)。直到父进程经过wait()系统调用知悉子进程终止以前,子进程都不会被彻底的清除。一旦父进程知道子进程终止,它会清除子进程的全部数据结构和进程描述符。

  • 3.3 线程

说到进程不得不提的就是线程了。线程是单个进程中生成的执行单元。多个线程在同一个进程中并发运行。它们共享内存、地址空间、打开文件等等资源。还能访问一样的应用数据集。线程也被称为轻量级进程(Light Weight Process)。因为线程间共享资源,线程不能同时改变它们共享的资源。互斥、锁、序列化等等都是由用户应用程序来实现。

从性能的角度看,建立线程比建立进程更加低消耗,由于建立线程不须要复制资源。另外一方面,从进程和线程在调度上看,他们拥有类似的行为。内核用相似的方法来处理他们。

下图是进程和线程的简单对比:

在当前的Linux实现中,线程由POSIX(Portable Operating System Interface for UNIX,可移 植操做系统接口)的兼容库(pthread)提供。Linux支持多线程。

  • 3.4 进程优先级和nice级别

进程优先级由动态优先级和静态优先级决定,它是决定进程在CPU中执行顺序的数字。优先级越高的进程被处理器执行的机会越大。

根据进程的行为,内核使用启发式算法决定开启或关闭动态优先级。能够经过nice级别直接修改进程的静态优先级,拥有越高静态优先级的进程会得到更长的时间片(时间片是进程在处理器中的执行时间)。

Linux支持的nice级别从19(最低优先级)到-20(最高优先级),默认只是0。只有root身份的用户才能把进程的nice级别调整为负数(让其具有较高优先级)。

  • 3.5 切换上下文

在进程执行过程当中,进程的信息存放在处理器的寄存器和缓存中。这部分执行中进程存放在寄存器中的数据就叫作context,上下文。在切换进程中,正在处理的进程上下文被保存起来,把下一个要执行的进程的上下文恢复到寄存器。上下文一般存储在进程描述符和内核态栈中。进程切换就叫作上下文切换(context switching)。由于处理器每次上下文切换都要为新进程刷新寄存器和缓存,可能引起性能上的问题,因此应该尽可能避免太多的上下文切换。 下图描述上下文切换是如何工做的:

  • 3.6 中断处理

中断处理是最高优先级别的任务之一。中断一般由I/O设备产生,譬如网络接口、键盘、磁盘控制器。中断处理器把键盘输入、网络帧到达这类事件通知给内核,它告诉内核尽快中断进程执行,由于某些设备须要快速的回应。这对系统稳定性是一个挑战。当中断信号到达内核,内核必须切换当前执行中的进程到新的进程,处理中断。这就意味着会发生上下文切换,同时也意味着大量的的中断会致使系统性能降低。

在Linux中有两类中断,硬中断是由设备产生的须要作出响应的中断,例如磁盘I/O中断,网卡中断,键盘和鼠标中断。软中断用于任务处理,能够推迟,例如TCP/IP操做、SCSI协议操做。能够在/proc/interrupts中看到相关的硬中断信息。

  • 3.7 进程状态

TASK_RUNNING 在这个状态中,进程正在CPU中执行,或者在运行队列(run queue)中等待运行。

TASK_STOPPED 进程因为特定的信号(如SIGINT、SIGSTOP)而挂起就会处于这个状态,等待恢复信号,好比SINCONT。

TASK_INTERRUPTIBLE 在此状态中,进程挂起而且等待一个特定的条件。假如进程处于TASK_INTERRUPTIBLE状态而且收到一个中止信号,进程状态会发生改变,操做会中断。TASK_INTERRUPTIBLE的典型例子是等待键盘中断。

TASK_UNINTERRUPTIBLE 相似于TASK_INTERRUPTIBLE。当进程处于TASK_INTERRUPTIBLE状态能够被中断,发送一个信号给TASK_UNINTERRUPTIBLE却不会有任何反应。TASK_UNINTERRUPTIBLE最典型的例子是进程等待磁盘I/O操做。

TASK_ZOMBIE 进程在使用exit()系统调用退出之后,父进程应该知道进程终结。在TASK_ZOMBIE状态中,进程在等待父进程收到通知并释放全部的数据结构。

它们之间的关系以下图:

说下僵尸进程

当进程已经收到信号而终止,正常状况下,彻底结束以前,它有一些时间来完成全部的任务(例如关闭打开的文件)。在这个很短的的正常的时间片里,这个进程是僵尸。

当进程完成了全部的关闭操做, 它向父进程报告它即将终结。有时候,僵尸进程不可以结束它本身,这个状态下,它就显示状态为Z(zombie)。

由于它已经死了,因此不可能使用kill命令杀死这种进程。若是没法摆脱僵尸进程,能够杀死僵尸进程的父进程,这样僵尸进程也会消失。而后,若是僵尸进程的父进程是init,你就别这么作了,init是很是重要的进程,你可能要重启才能摆脱僵尸进程了。

  • 3.8 进程内存段

进程使用本身的内存区域处理任务,任务种类由场景和进程用途决定。进程有不一样的工做特性和不一样数据大小要求,进程必须处理各类大小的数据。为知足这一要求,Linux内核给各个进程使用动态内存分配机制。进程内存分配结构以下图:

进程内存区域包含以下段:

文本 :存储可执行代码的区域
数据 : 数据段由以下三个区域构成
    Data:存储初始化数据,好比静态变量
    BSS:存储初始化0数据,数据初始化为0
    Heap(堆):根据须要使用malloc()分配动态内存。堆向高地址空间增加。
栈: 该区域存储局部变量、函数参数和函数的返回地址。栈向低地址空间增加。
复制代码

用户进程的地址空间分配可使用pmap命令显示出来。你可使用ps命令显示总的段大小。

  • 3.9 Linux的CPU调度

计算机的最基本功能就是计算,为了实现计算功能,必需要有办法管理计算资源、处理器、计算任务,也就是常说的进程和线程。

下面谈下Linux中CPU调用进程的算法,这个算法使用两个进程优先级数组:

1.active
2.expired
复制代码

因为调度器根据进程的优先级和先前阻塞率来位分配时间片,进程的优先级被放在一个active数组中。当时间片到期,它们被从新分配新的时间片,而且放置到expired数组上。当全部active数组上的进程都到期,active和expired数组发生对换,重启算法。对于通常的交互进程(对应实时进程),高优先级的进程一般会比低优先级进程分配更多的时间片,可是并不意味着彻底不给低优先级进程机会。

以下展现和Linux的CPU调度器是如何工做的:

新调度器的另一个大有有点是支持非均匀内存架构(Non-Uniform Memory Architecture, NUMA)和对称多线程处理器,例如Intel的超线程技术。支持NUMA保证了正常状况下不会出现负载均衡的状况,除非一个节点负担太重。这个机制保证了在NUMA系统中,比较缓慢的链路负载较小。尽管在一个组中的处理器调度的每个处理,会被负载均衡,可是调度器的组只会在节点负载太高和要求负载均衡的时候产生。

4、下一节是???

谈完Linux的进程管理,下一节谈一下 Linux的内存体系

相关文章
相关标签/搜索