Linux内核进程

1.1 Linux进程管理

进程管理是操作系统的最重要的功能之一。有效率的进程管理能保证一个程序平稳而高效地运行。
Linux的进程管理与UNIX的进程管理相似。它包括进程调度、中断处理、信号、进程优先级、上下文切换、进程状态、进度内存等。
1.1.1 什么是进程?
一个进程是处于执行期的程序(目标码存放在某种介质上)。但是不局限于一段可执行的代码,通常进程还包括其他资源,比如打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程,还包括用来存储数据的数据段。

执行线程, 线程,是在进程中活动的对象。每个线程用于独立的的程序计数器,进程栈,和一组进程寄存器。内核调度的对象是线程而不是进程。linux系统线程的实现非常特别,对线程与进程并不特别区分。对Linux而言,线程是特殊的进程。

现代操作系统为进程提供两种虚拟机制:虚拟处理器以及虚拟内存。虚拟处理器让进程感觉自己在独享处理器。虚拟内存让进程在分配管理内存时觉得自己拥有整个系统的内存资源。

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

一个进程的创建是通过fork调用实现,调用之后并不会复制父进程的地址空间,父子进程共享相同的地址空间(以只读形式共享)。exec系统调用复制新的程序到子进程的地址空间。因为父子进程共享地址空间,写入一个新的程序的数据会引起一个分页错误。这种情况下,内存会分配新的物理内存空间给子进程。这个推迟的操作叫做写时复制。

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

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

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

1.1.2  进程描述符以任务结构

内核把进程的列表存放在任务队列的双向循环链表中,链表的每一项都是类型为task_struct称为进程描述符的结构。进程描述符包含一个进程的所有信息。其中包含的信息能够完整的描述一个可执行程序:打开的文件 进程的地址空间
挂起的信号 进程的状态 还有其他更多的信息。Linux通过Slab分配器来分配task_struct结构,这样能达到对象复用和缓存着色的目的。(通过预先分配和重复使用task_struct 可以避免动态分配和释放带来的资源消耗)。这样可以让进程的创建更加迅速。

1.1.3 进程状态

每一个进程拥有自己的状态,状态表示了进程当前在发生什么。在进程的执行期间进程的状态会发生改变。一些进程的状态如下:

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.1.4 上下文切换

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


1.1.5 线程在Linux中的实现
线程机制是现代编程技术中常用的一种抽象概念。该机制提供了同一程序内共享内存地址空间运行的一组线程。Linux实现线程的机制特别独特,从内核的角度来讲的话,并没有线程的概念。Linux把所有的线程当做进程来实现。线程仅仅被视为一个与其他进程共享某些资源的进程。每一个线程都拥有唯一隶属于自己的task_struct 所以在内核中,他看起来像一个普通的进程。
1.1.6进程内存段

进程内存区由以下几部分组成:
Text段
该区域用于存储运行代码。

Data段
数据段包括三个区域。
- Data:该区域存储已被初始化的数据,如静态变量。
- BSS:该区域存储初始化为0的数据。数据被初始化为0。
- Heap:该区域用于根据需求使用malloc()动态申请的内存。堆向高地址方向增长。

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


用户进程的地址空间内存分布可以使用pmap命令来查看。你可以使用ps命令来查看内存段的大小


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值