Linux内核-进程

11 篇文章 1 订阅
3 篇文章 0 订阅

Linux中的进程

简介

一般来说,Linux系统中的进程都具有下列要素:

  • 有一段程序供其执行,这段程序不一定是进程所专有,可以与其它进程共用
  • 有起码的“私有财产”,这就是进程专有的系统堆栈空间
  • 有“户口”,这就是在内核中的一个task_struct数据结构,即进程描述符,有了这个数据结构,进程才能成为内核调度的一个基本单位接收内核的调度
  • 有独立的存储空间,意味着拥有专有的用户空间;进一步,还意味着除前述的系统空间堆栈外还有其专有的用户空间堆栈。

上面四条都是必要条件。如果只具备了前面两条而缺少第四条,就称为“线程”。特别的,如果万千没有用户空间,就称为“内核线程”;如果共享用户空间就称为“用户线程”。

对每个进程来说,Linux把两个不同的数据结构紧凑地放在一个单独为进程分配的存储区域内:一个是内核态的进程堆栈,另一个是紧挨进程描述符的小数据结构thread_info,叫做线程描述符,这块存储区域的大小通常为8192个字节(两个页框)。Linux通过slab分配器为进程分配task_struct,而通过分区页框分配器为进程分配上述所说的(两个页框)存储区,它们的关系如下图:

这里写图片描述

当进程从用户态切换到内核态时,就会使用上述堆栈。Linux使用联合体thread_union表示上图中每个进程的线程描述符和内核栈:

/**
 * 内核栈与thread_info的联合体。
 */
union thread_union {
    struct thread_info thread_info;
    unsigned long stack[THREAD_SIZE/sizeof(long)];
};

thread_info和内核堆栈之间紧密结合的主要好处是:内核很容易从esp寄存器的值获得当前CPU上正在运行进程的thread_info结构的地址,从而得到task_struct。

每个进程都不是孤立地存放在系统中的,而是根据不同的目的、关系和需要与其它的进程相联系。有了上面的基本认识之后,现在来看下内核中进程的几种组织方式:

  • 由每个进程的“家庭与社会关系”形成的“家谱”。这是一种树型组织。
  • 为了根据pid方便找到进程,内核为进程创建了散列表,用链表解决冲突。
  • 当需要对每个进程做点什么事情时,需要将所有进程组织成一个线性的队列。

每个进程都必然同时身处这三个队列之中,直到进程消亡。除此之外,在运行的过程中,一个进程还可以动态的链接进“等待队列”或“可执行队列”等队列中接收系统的调度。


进程描述符

为了管理进程,内核必须对每个进程所做的事情进行清楚的描述。例如,内核必须知道进程的优先级,它是正在CPU上运行还是因某些事情而被阻塞,给它分配了什么样的地址空间,允许它访问哪个文件等等。这正是进程描述符task_struct的作用,下面列出主要字段:

这里写图片描述


进程的地址空间

内核中的函数以直接了当的方式获得动态内存,也就是说,当内核函数请求内存时,Linux会马上分配物理内存给进程;而当用户态进程请求动态内存时,Linux认为是不紧迫的,此时并没有获得请求的页框,而仅仅获得对一个线性地址区间的使用权。所以,进程的地址空间由允许进程使用的全部线性地址组成,每个进程过看到的线性地址集合是不同的,一个进程所使用的地址与另外一个进程所使用的地址之间没有什么关系,也就是说,两个进程可以使用相同的线性地址,这是由内存的分页机制实现的,每个进程都有自己的页表,用来把线性地址转换为物理地址,所以,两个进程的相同线性地址可以通过各自的页表映射到不同的物理地址。

与进程地址空间有关的全部信息都包含在一个叫做内存描述符的数据结构中,这个结构的类型为mm_struct,如下图所示:

这里写图片描述

进程所拥有的所有线性区是通过一个简单的链表链接在一起的,这些线性区是按内存地址的升序排列的,为维持这些顺序及提高查找的效率,Linux又把这些线性区描述符存放在红黑树中。

Linux进程的线性地址空间布局如下,对不同的系统,用户空间和内核空间比例不一样,对于32位系统来说,内核空间为3~4G,而用户空间为0~3G:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值