热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux性能及调优指南:进程管理文章伯乐在线

1.1Linux进程管理进程管理是操作系统的最重要的功能之一。有效率的进程管理能保证一个程序平稳而高效地运行。Linux的进程管理与UNIX的进程管理相似。它包括进程调度、中断处理


1.1 Linux进程管理


进程管理是操作系统的最重要的功能之一。有效率的进程管理能保证一个程序平稳而高效地运行。


Linux的进程管理与UNIX的进程管理相似。它包括进程调度、中断处理、信号、进程优先级、上下文切换、进程状态、进度内存等。


在本节中,我们将描述Linux进程管理的基本原理的实现。它将更好地帮助你理解Linux内核如何处理进程及其对系统性能的影响。


1.1.1 什么是进程?


一个进程是一个运行在处理器的程序的一个实例。该进程使用Linux内核能够处理的任何资源来完成它的任务。


所有运行在Linux操作系统中的进程都被task_struct结构管理,该结构同时被叫作进程描述。一个进程描述包含一个运行进程所有的必要信息,例如进程标识、进程属性和构建进程的资源。如果你了解该进程构造,你就能理解对于进程的运行和性能来说,什么是重要的。图1-2展示了进程结构相关的进程信息概述。



图1-2task_struct结构体


1.1.2 进程的生命周期


每一个进程都有其生命周期,例如创建、运行、终止和消除。这些阶段会在系统启动和运行中重复无数次。因此,进程的生命周期对于其性能的分析是非常重要的。


图1-3展示了经典的进程生命周期。



图1-3经典的进程生命周期


当一个进程创建一个新的进程,进程的创建进程(父进程)调用 一个fork()系统调用。当fork()系统调用被调用,它得到该新创建进程(子进程)的进程描述并调用一个新的进程id。它复制该值到父进程进程描述到子进程中。此时整个的父进程的地址空间是没有被复制的;父子进程共享相同的地址空间。


exec()系统调用复制新的程序到子进程的地址空间。因为父子进程共享地址空间,写入一个新的程序的数据会引起一个分页错误。在这种情况下,内存会分配新的物理内存页给子进程。


这个推迟的操作叫作写时复制。子进程通常运行他们自己的程序而不是与父进程运行相同的程序。这个操作避免了不必要的开销,因为复制整个地址空间是一个非常缓慢和效率低下的操作,它需要使用大量的处理器时间和资源。


当程序已经执行完成,子进程通过调用exit()系统调用终止。exit()系统调用释放进程大部分的数据并通过发送一个信号通知其父进程。此时,子进程是一个被叫作僵尸进程的进程(参阅page 7的“Zombie processes”)。


子进程不会被完全移除直到其父进程知道其子进程的调用wait()系统调用而终止。当父进程被通知子进程终止,它移除子进程的所有数据结构并释放它的进程描述。


1.1.3 线程


一个线程是一个单独的进程生成的一个执行单元。它与其他的线程并行地运行在同一个进程中。各个线程可以共享进程的资源,例如内存、地址空间、打开的文件等等。它们能访问相同的程序数据集。线程也被叫作轻量级的进程(Light Weight Process,LWP)。因为它们共享资源,所以每个线程不应该在同一时间改变它们共享的资源。互斥的实现、锁、序列化等是用户程序的责任。


从性能的角度来说,创建线程的开销比创建进程少,因数创建一个线程时不需要复制资源。另一方面,进程和线程拥在调度算法上有相似的特性。内核以相似的方式处理它们。



图1-4 进程和线程


在现在的Linux实现中,线程支持UNIX的可移植操作系统接口(POSIX)标准库。在Linux操作系统中有几种可用的线程实现。以下是广泛使用的线程库:


LinuxThreads


LinuxThreads自从Linux内核2.0起就已经被作为默认的线程实现。LinuxThreads的一些实现并不符合POSIX标准。Native POSIX Thread Library(NPTL)正在取代LinuxThreads。LinuxThreads在将来的Linux企业发行版中将不被支持。


Native POSIX Thread Libary(NPTL)


NPTL最初是由红帽公司开发的。NPTL与POSIX更加兼容。通过Linux内核2.6的高级特性,例如,新的clone()系统调用、信号处理的实现等等,它具有比LinuxThreads更高的性能和伸缩性。


NPTL与LinuxThreads有一些不兼容。一个依赖于LinuxThreads的应用可能不能在NPTL实现中工作。


Next Generation POSIX Thread(NGPT)


NGPT是一个IBM开发的POSIX线程库。现在处于维护阶段并且在未来也没有开发计划。


使用LD_ASSUME_KERNEL环境变量,你可以选择在应用中使用哪一个线程库。


1.1.4 进程优先级和nice值


进程优先级是一个数值,它通过动态的优先级和静态的优先级来决定进程被CPU处理的顺序。一个拥有更高进程优先级的进程拥有更大的机率得到处理器的处理。


内核根据进程的行为和特性使用试探算法,动态地调整调高或调低动态优先级。一个用户进程可以通过使用进程的nice值间接改变静态优先级。一个拥有更高静态优先级的进程将会拥有更长的时间片(进程能在处理上运行多长时间)。


Linux支持从19(最低优先级)到-20(最高优先级)的nice值。默认值为0。把程序的nice值修改为负数(使进程的优先级更高),需要以root身份登陆或使用su命令以root身份执行。


1.1.5 上下文切换


在进程运行过程中,进程的运行信息被保存于处理器的寄存器和它的缓存中。正在执行的进程加载到寄存器中的数据集被称为上下文。为了切换进程,运行中进程的上下文将会被保存,接下来的运行进程的上下文将被被恢复到寄存器中。进程描述和内核模式堆栈的区域将会用来保存上下文。这个切换被称为上下文切换。过多的上下文切换是不受欢迎的,因为处理器每次都必须清空刷新寄存器和缓存,为新的进程制造空间。它可能会引起性能问题。


图1-5 说明了上下文切换如何工作。



图1-5 上下文切换


1.1.6 中断处理


中断处理是优先级最高的任务之一。中断通常由I/O设备产生,例如网络接口卡、键盘、磁盘控制器、串行适配器等等。中断处理器通过一个事件通知内核(例如,键盘输入、以太网帧到达等等)。它让内核中断进程的执行,并尽可能快地执行中断处理,因为一些设备需要快速的响应。它是系统稳定的关键。当一个中断信号到达内核,内核必须切换当前的进程到一个新的中断处理进程。这意味着中断引起了上下文切换,因此大量的中断将会引起性能的下降。


在Linux的实现中,有两种类型的中断。硬中断是由请求响应的设备发出的(磁盘I/O中断、网络适配器中断、键盘中断、鼠标中断)。软中断被用于处理可以延迟的任务(TCP/IP操作,SCSI协议操作等等)。你可以在/proc/interrupts文件中查看硬中断的相关信息。


在多处理器的环境中,中断被每一个处理器处理。绑定中断到单个的物理处理中能提高系统的性能。更多的细节,请参阅4.4.2,“CPU的中断处理亲和力”。


1.1.7 进程状态


每一个进程拥有自己的状态,状态表示了进程当前在发生什么。


在进程的执行期间进程的状态会发生改变。一些进程的状态如下:


TASK_RUNNING


在此状态下,表示进程正在CPU中运行或在队列中等待运行(运行队列)。


TASK_STOPPED


在此状态下的进程被某些信号(如SIGINT,SIGSTOP)暂停。进程正在等待通过一个信号恢复运行,例如SIGCONT。


TASK_INTERRUPTIBLE


在此状态下,进程被暂停并等待一个某些条件状态的到达。如果一个进程处于TASK_INTERRUPTIBLE状态并接收到一个停止的信号,进程的状态将会被改变并中断操作。一个典型的TASK_INTERRUPTIBLE状态的进程的例子是一个进程等待键盘中断。


TASK_UNINTERRUPTIBLE


与TASK_INTERRUPTIBLE相似。当一个进程处于TASK_UNINTERRUPTIBLE状态可以被中断,向处于TASK_UNINTERRUPTIBLE状态的进程发送一个信号不会发生任何操作。一个TASK_UNINTERRUPTIBLE进程的典型的例子是等待磁盘I/O操作。


TASK_ZOMBIE


当一个进程调用exit()系统调用退出后,它的父进程应该知道该进程的终止。处于TASK_ZOMBIE状态的进程会等待其父进程通知其释放所有的数据结构。



图1-6 进程状态


僵尸进程


当一个进程接收到一个信号而终止,它在结束自己之前,通常需要一些时间来结束所有的任务(例如关闭打开的文件)。在这个通常非常短暂的时间内,该进程就是一个僵尸进程。


进程已经完成所有的关闭任务后,它会向父进程报告其即将终止。有些时候,一个僵尸进程不能把自己终止,这将会引导它的状态显示为z(zombie)。


使用kill命令来关闭这样的一个进程是不可能的,因为该进程已经被认为已经死掉了。如果你不能清除僵尸进程,你可以结束其父进程,然后僵尸进程也随之消失。但是,如果父进程为init进程,你不能结束它。init进程是一个非常重要的进程,因此可能需要重启系统来清除僵尸进程。


1.1.8 进程内存段


进程使用其自身的内存区域来执行工作。工作的变化根据情况和进程的使用而决定。进程可以拥有不同的工作量特性和不同的数据大小需求。进程必须处理各种数据大小。为了满足需求,Linux内核为每个进程使用动态申请内存的机制。进程内存分配的数据结构如图1-7所示。



图1-7 进程地址空间


进程内存区由以下几部分组成:


Text段


该区域用于存储运行代码。


Data段


数据段包括三个区域。


– Data:该区域存储已被初始化的数据,如静态变量。


– BSS:该区域存储初始化为0的数据。数据被初始化为0。


– Heap:该区域用于根据需求使用malloc()动态申请的内存。堆向高地址方向增长。


Stack段


该区域用于存储局部变量、函数参数和返回函数的地址。栈向低地址方向增长。


用户进程的地址空间内存分布可以使用pmap命令来查看。你可以使用ps命令来查看内存段的大小。可以参阅2.3.10的“pmap”,“ps和pstree”。


1.1.9 Linux CPU调度


任何的计算机的基本功能都非常简单,就是计算。为了能够计算,它意味着必须管理计算资源或处理器和计算任务,也就是我们所知道的线程或进程。感谢Ingo Molnar的巨大贡献,Linux内核使用一个O(1)的算法代替以前的O(n)的CPU调度算法。O(1)指的是一种静态的算法,意味着选择一个进程并执行所花费的时间是一个常数,不管进程的数量的大小。


新的调度算法的扩展性非常好,不管进程的数量或者处理器的数量是多少,系统的开销都是非常少的。该算法使用两个进程优先级数组:


active(活动的)


expired(过期的)


调度器根据进程的优先级和优先拦截率为进程分配时间片,然后进程以优先级顺序放置到active数组内。当进程时间片耗尽,进程申请一个新的时间片并放置到expired数组内。当active数组中的所有进程的时间片耗尽,这两个数组进行切换,重新运行该算法。对于一般的交互式进程(相对于实时进程),拥有高优先级的进程通常比低优先级的进程得到更长的时间片和更多的计算时间,但这并不表示低优先级的进程会被完全忽略(饿死)。该算法的优势是为拥有大量线程和进程并拥有多处理器的企业级环境提升Linux内核的扩展性。该O(1)的新CPU调度器是为内存2.6设计的,但是现在已经移植到2.4系列中。图1-8说明了Linux CPU如何调度工作。



图1-8 Linux内核2.6 O(1)调度器


新调度器的另一个显著改进是支持非一致性内存架构(NUMA)和对称多线程处理器,例如Intel超线程技术。


改进后的NUMA支持确保只有某个节点过载时,负载平衡才会跨越某个NUMA节点。这个机制确保了在NUMA系统相对比较缓慢的扩展链接流量的最小化。尽管每个调度节拍时负载平衡会遍历调度域群组中的处理器,但只有在节点过载并请求负载平衡时,负载才会跨越调度域转移。



图1-9 O(1)CPU调度器结构




推荐阅读
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
author-avatar
9asd8fy
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有