Linux内核进程管理

发表于:2015-7-24 10:08

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:mfrbuaa    来源:51Testing软件测试网采编

  介绍:
  在Linux的内核的五大组成模块中,进程管理模块时很重要的一部分。它尽管不像内存管理、虚拟文件系统等模块那样复杂。也不像进程间通信模块那样条理化,但作为五大内核模块之中的一个,进程管理对我们理解内核的运作、对于我们以后的编程很重要。同一时候。作为五大组成模块中的核心模块。它与其它四个模块都有联系。
  以下就对进程模块进行想写的介绍,首先要了解进程及其相关的概念。其次介绍进程的创建、切换、撤销等基本操作。除此之外,还给出了Linux内核是怎样对进程进行调度管理的。
  一、进程及其相关概念
  进程:进程能够理解为程序运行的一个实例,它包括可运行程序以及与其相关的系统资源,比方打开的文件、挂起的信号、内核内部数据、处理器状态、内存地址空间及包括全局变量的数据段等。
  从内核的角度看,进程也能够称为任务。
  进程描写叙述符:与进程相关的事情许多。比方进程的状态、进程的优先级、进程的地址空间、同意该进程訪问的文件等等,Linux内核为此专门设计了一个类型为task_struct的结构体,称之为进程描写叙述符。进程描写叙述符中包括了内核管理进程的全部信息。能够说,仅仅要得到一个进程的进程描写叙述符,就能够知道一个进程的全部信息。
  进程状态:进程描写叙述符task_struct结构体中有一个state字段,表示进程当前的所处状态。从进程的创建到进程的删除。它能够经过5种不同的状态。各自是可执行状态、可中断的等待状态、不可中断的等待状态、暂停状态、跟踪状态。
  除此之外,当进程被终止时,还可能会变为僵死状态、僵死撤消状态。内核能够使用宏set_current_state(state)设置当前进程的状态,用set_task_state(task,state)设置某进程的状态。
  进程标示符:进程描写叙述task_struct结构体中的pid字段能够标识唯一标识一个进程,称之为进程标识符PID。当创建一个新进程时,PID是依照顺序从小到大分配给新进程的。内核通过管理一个pidmap_array位图来表示当前已分配的PID和闲置的PID号。
  注意:在多线程组中。全部的线程共享同样的PID。
  除了进程标识符外,内核对进程的大部分訪问时通过进程描写叙述符指针进行的。
  进程关系:进程之间的关系有亲属关系和非亲属关系。亲属关系包含父子关系和兄弟关系等。当中由tast_struct结构体中的parent/children/real_parent/sibling等字段描写叙述。
  除了亲属关系外,还有其它关系,比方,一个进程是一个进程组或登录会话的领头进程,可能是一个线程组的领头进程。这些关系由group_leader/tgid/signal->pgrp等字段描写叙述。
  进程资源:为了防止进程过度的使用系统资源。内核为每一个进程使用资源的数量进行了一些限制。
  当中包含进程地址空间的最大数、进程使用CPU的最大时间、堆的最大值、文件大小的最大值、文件锁数量的最大值、消息队列的最大字节数、打开文件描写叙述符的最大数、进程拥有的页框最大数等。
  二、进程的创建、切换、撤销
  进程的创建:在Linux环境编程时,一般採用fork()函数来创建新的进程,当然。那是在用户空间的函数。它会调用内核中的clone()系统调用,由clone()函数继续调用do_fork()完毕进程的创建。
  传统Unix系统中,创建的子进程复制父进程所拥有的资源,这样的方法效率低,由于子进程须要拷贝父进程的整个地址空间。
  可是,子进程差点儿不必读或改动父进程拥有的全部资源,由于非常多情况下,子进程创建后会马上调用exec()一族的函数。并清除父进程细致拷贝过来的地址空间。现代Unix系统用三种方式攻克了这个问题:1、写实复制技术同意父子进程读同样的物理页。
  2、轻量级进程同意父子进程共享每进程在内核的非常多数据结构。3、vfork()系统调用创建的进程能共享父进程的内存地址空间,为了防止父进程重写子进程须要的数据。堵塞父进程的运行,一直到子进程退出或运行一个新的程序为止。整个进程创建过程可能涉及到例如以下函数:
  fork()/vfork()/_clone----------->clone()--------->do_fork()---------->copy_process()
  上面的创建过程结束之后,就有了处于可执行状态的完整的子进程,新的子进程有了PID、进程描写叙述符等各种数据结构。要想实际执行它,还须要调度程序把CPU交给新创建的子进程。
  除了进程外,还有内核线程(用kernet_thread创建)的概念。
  在Linux中。内核线程与普通进程存在下面两个方面的不同:
  1、内核线程仅仅执行在内核态。而普通进程既能够执行在内核态,也可执行在用户态。
  2、由于内核线程仅仅执行在内核态。它仅仅使用大于PAGE_OFFSET的线性地址空间。
  还有一方面。无论在用户态还是在内核态,普通进程能够用4GB的线性地址空间。
  撤销进程:进程终止后,须要通知内核以便内核释放进程所拥有的资源。包含内存、打开文件以及其它资源。如信号量。进程终止的一般方式是调用exit()库函数,该函数释放C函数库所分配的资源,运行编程者所注冊的每一个函数,并结束从系统回收进程的那个系统调用。
  除了进程自己终止自己外。内核能够有选择地强迫整个线程组死掉。这发生在:当进程接收到一个不能处理或忽视的信号时,或者当内核正在代表进程执行时再内核态产生一个不可恢复的CPU异常时。
  有两个终止用户态应用的系统调用:exit_group()系统调用,它终止整个线程组,即整个基于多线程的应用。do_group_exit()是实现这个系统调用的主要内核函数。
  exit()系统调用,它终止一个线程,而无论该线程所属线程组中的全部其它进程。do_exit()是实现这个系统调用的主要内核函数。
  进程切换:进程切换又称为任务切换、上下文切换。它是这样一种行为,为了控制进程的运行,内核挂起当前在CPU上运行的进程。并恢复曾经挂起的某个进程的运行。
  跟函数的调用类似。进程切换时。一般要在CPU上装载要运行进程的进程上下文。
  进程的硬件上下文指:可运行程序上下文的一个子集,是进程恢复运行前装入寄存器的一组数据。
  当中一部分放在TSS段。即任务状态段。剩余部分存放在内核态堆栈中。
  进程的切换仅仅发生在内核态,在运行进程切换之前。用户态进程使用的全部寄存器内容都已保存在内核态堆栈上。
  进程的切换有两种方法,一种是硬件切换,一种是软件切换。软件切换就是利用程序逐步运行切换,它的长处是。能够对切换时装入的数据进行合法性检查,运行时间虽与硬件切换大致同样,但仍有可改进的地方。
  进程切换使用schedule()函数完毕,在本质上。每一个进程切换由两部分组成:1、切换页全局文件夹以安装一个新的地址空间。2、切换内核态堆栈和硬件上下文,由于硬件上下文提供了内核运行新进程所须要的全部信息,包含CPU寄存器。主要有switch_to函数完毕。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号