疯狂内核之进程管理
文章平均质量分 88
yunsongice
这个作者很懒,什么都没留下…
展开
-
进程相关的数据结构
为了管理进程,内核必须对每个进程所做的事情进行清楚的描述。例如,内核必须知道进程的优先级,它是正在CPU上运行还是因某些事件而被阻塞,给它分配了什么样的地址空间,允许它访问哪个文件等等。这些正是进程描述符的作用——进程描述符都是task_struct数据结构,它的字段包含了与一个进程相关的所有信息。因为进程描述符存放了那么多的信息,所以它是相当复杂滴。。。。不过别怕,我们解决主要矛盾,其他原创 2010-04-18 17:19:00 · 6410 阅读 · 2 评论 -
64位x86体系Linux内核进程切换
首先简单提一下这个宏和函数的被调用关系: schedule() --> context_switch() --> switch_to --> __switch_to() 这里面,schedule是唯一调用switch_to的函数,涉及到一些调度算法,这里不讨论。当schedule()需要暂停A进程的执行而继续B进程的执行时,就发生了进程之间的切换。进程切换主要有两大步:1、原创 2013-01-27 21:30:04 · 6105 阅读 · 0 评论 -
recalc_task_prio函数
函数recalc_task_prio更新进程p的平均睡眠时间和动态优先级,更重要的是,他还通过平均睡眠时间判断进程是否是交互进程。它接收进程描述符的指针p和由函数sched_clock()计算出当前时间戳now作为参数。static int recalc_task_prio(struct task_struct *p, unsigned long long now){ /*原创 2010-04-25 11:44:00 · 4233 阅读 · 0 评论 -
scheduler_tick函数
本博,我们详细分解每次定时器中断调用的最重要的更新时间片的函数 —— scheduler_tick函数当每次时钟节拍到来时,即我们提到过的timer_interrupt会调用do_timer_interrupt_hook,从而调用do_timer和update_process_times函数,update_process_times则就是用来更新进程使用到的一些跟时间相关的字段,其罪重要的原创 2010-04-25 11:39:00 · 6915 阅读 · 1 评论 -
进程调度的数据结构和优先级
1 进程的优先级每个普通进程都有它自己的静态优先级,位于task_struct的static_prio字段,调度程序使用静态优先级来估价系统中这个进程与其它普通进程之间调度强度。但是,注意,调度程序不是根据静态优先级来决定调度哪个进程的,而是动态优先级,后面会详细谈到。内核用100(最高优先级)到139(最低优先级)的整数表示普通进程的静态优先级。注意,值越大静态优先级就越低。原创 2010-04-25 11:10:00 · 6642 阅读 · 0 评论 -
非运行状态进程的组织
在详细讲解运行进程的组织及调度的一些列课题前,先把Linux内核中如何组织非运行状态进程的那些机制梳理一遍。运行队列链表rq把处于TASK_RUNNING状态的所有进程组织在一起。当要把其他状态的进程分组时,不同的状态要求不同的处理,Linux选择了下列方式之一:(1) 没有为处于TASK_STOPPED、EXIT_ZOMBIE 或 EXIT_DEAD状态的进程建立专门的链表。由于原创 2010-04-25 09:48:00 · 4310 阅读 · 0 评论 -
内核线程
按照传统UNIX规定的一些操作系统标准,一些重要的任务需要由进程来周期性地执行。这些任务包括刷新磁盘高速缓存,交换出不用的页框,维护网络连接等等。那么,由于这些系统进程只运行在内核态,所以Linux将他改造了,跟一般的进程不一样了,给它取个名称叫内核线程(kernel thread)。这个内核线程跟普通进程最大的区别就是,只运行在内核态,不受不必要的用户态上下文的拖累。在Linux中,内核线程在以原创 2010-04-23 19:37:00 · 3871 阅读 · 2 评论 -
schedule()函数(重点)
好了,前面的准备工作都做完了,我们就进入进程调度的主体程序——schedule()函数。函数schedule()实现调度程序。它的任务是从运行队列的链表rq中找到一个进程,并随后将CPU分配给这个进程。schedule()可以由几个内核控制路径调用,可以采取直接调用或延迟调用(可延迟的)的方式。下面,我们就来详细介绍。1 直接调用 如果current进程因不能获得必须的资源而要原创 2010-04-25 11:45:00 · 11914 阅读 · 2 评论 -
进程调度的概念
从本博开始,我们就要慢慢深入到进程管理乃至整个内核的核心概念——进程调度里边了。这里,先把相关概念理一理。 刚接触Linux,我们就讲了,它是一个分时系统,却由具备实时系统的特性。所以与任何分时系统一样,通过一个进程到另一个进程的快速切换,达到表面上看来多个进程同时执行的神奇效果。我们已经在前面的博文中讲过了进程切换的本身已,从本博开始,我们将进入进程管理最最最重要的部分——进程的调度,主原创 2010-04-25 10:44:00 · 3788 阅读 · 0 评论 -
执行进程间切换
1 进程切换之前的工作由于每个进程共享CPU寄存器(咱们就当是单CPU吧),因此在恢复一个进程之前,内核必须确保每个寄存器装入挂起进程时的值,他们就叫“硬件上下文”。在Linux中,进程硬件上下文得一部分放在TSS段,主要用于对内核态堆栈进行寻址,而剩余部分放在内核态堆栈中。我们再回忆一下硬件中TSS段的内容:struct tss_struct { unsigned short b原创 2010-04-22 15:01:00 · 7050 阅读 · 4 评论 -
进程退出
很多进程终止了他们本该执行的代码,从这种意义上说,他们已经“死”了。当这种情况发生时,必须通过内核以便内核释放进程所拥有的资源。进程终止的一般方式是调用exit()库函数,该函数释放C函数库所分配的资源,执行编程者所注册的每个函数,并结束从系统回收进程所执行的那个系统调用。内核可以有选择地强迫整个线程组死掉。这发生在以下两种典型情况下:当进程接收到一个不能处理或忽视的信号时,或者当原创 2010-04-25 12:35:00 · 2312 阅读 · 1 评论 -
try_to_wake_up函数
try_to_wake_up函数通过把进程状态设置为TASK_RUNNING,并把该进程插入本地CPU运行队列rq来达到唤醒睡眠和停止的进程的目的。例如:调用该函数唤醒等待队列中的进程,或恢复执行等待信号的进程。该函数接受的参数有:- 被唤醒进程的描述符指针(p)- 可以被唤醒的进程状态掩码(state)- 一个标志(sync),用来禁止被唤醒的进程抢占本地CPU上正在运行的进程原创 2010-04-25 11:41:00 · 7129 阅读 · 0 评论 -
多处理器运行队列的平衡
Linux一直坚持采用对称多处理模式,这意味着,与其他CPU相比,内核不对一个CPU有任何偏向,但是,多处理器机器具有很多不同的风格,而且调度程序的实现随硬件特征的不同而有所不同,我们将特别关注下面三种不同类型的多处理器机器:(1)标准的多处理器体系结构直到最近,这是多处理器机器最普通的体系结构。这些机器所共有的RAM芯片集被所有CPU共享。(2)超线程超线程芯片是原创 2010-04-25 12:22:00 · 5841 阅读 · 0 评论 -
fork与vfock系统调用的区别
fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别:1. fork():子进程拷贝父进程的数据段,代码段 vfork():子进程与父进程共享数据段2. fork():父子进程的执行次序不确定 vfork保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之后父进程才可能被调度运行。3. vfor原创 2010-04-22 16:12:00 · 3565 阅读 · 0 评论 -
进程的创建 —— do_fork()函数详解
在讲进程管理专题最核心的课题——进程创建之前,我们先简单地回顾一下上一篇博文的sys_clone()系统调用:asmlinkage int sys_clone(struct pt_regs regs){ unsigned long clone_flags; unsigned long newsp; int __user *parent_tidptr, *chi原创 2010-04-20 19:53:00 · 14612 阅读 · 0 评论 -
Linux的线程——轻进程
进程类似于人生:它们被产生,有或多或少有效的生命,可以产生一个或多个子进程,最终都要死亡。一个微小的差异是进程之间没有性别差异——每个进程都只有一个父亲。那么,操作系统有一个重要的概念——线程,在Linux上是怎么实现的呢?可以明确的告诉你,Linux并没有线程这个概念。呵呵,是不是Linux很落后呢,不是,恰恰相反,Linux提供了另一个概念——轻进程,其更具有扩展性,更伟大。Linux原创 2010-04-20 11:37:00 · 4751 阅读 · 2 评论 -
一个简单的内核线程
一个简单的linux内核线程的例子,根据精通linux设备驱动上的代码整合而成。#include #include #include #include MODULE_LICENSE("GPL");static DECLARE_WAIT_QUEUE_HEAD(myevent_waitqueue); //声明了一个等待队列头,我们可以将要睡眠的进程放入本列表static struc转载 2013-07-25 16:52:29 · 3675 阅读 · 1 评论