当前位置:  技术问答>linux和unix

求助!关于linux内核0.11版本进程睡眠调度的疑问?

    来源: 互联网  发布时间:2016-11-21

    本文导语:  本人刚开始学linux内核,由于基础太差就从赵炯编写的《linux内核完全注释》开始看,其中关于sched.c中的代码sleep_on (struct task_struct **p)与interruptible_sleep_on (struct task_struct **p)两个函数,其中sleep_on中是否应该加*p=tmp...

本人刚开始学linux内核,由于基础太差就从赵炯编写的《linux内核完全注释》开始看,其中关于sched.c中的代码sleep_on (struct task_struct **p)与interruptible_sleep_on (struct task_struct **p)两个函数,其中sleep_on中是否应该加*p=tmp与wake_up中的*p=NULL是否应该去掉?遗留等待队列头指针有何用?
  还有这个版本的内核好像没有把可中断等待任务队列与不可中断任务等待队列分开,我不知道是否应该有两个队列,难道将两个队列和合在一起,但如果其中有一个是可中断的,那么好像只要有一个软中断信号发给它,它就能连不可中断的等待任务一起唤醒。我不知道算不算是这一版本的bug。如果有懂的朋友或熟悉最新版本内核的朋友恳请指导一下,
非常感谢,代码如下。


void
schedule (void)
{
  int i, next, c;
  struct task_struct **p; // 任务结构指针的指针。

  /* check alarm, wake up any interruptible tasks that have got a signal */
  /* 检测alarm(进程的报警定时值),唤醒任何已得到信号的可中断任务 */

  // 从任务数组中最后一个任务开始检测alarm。
  for (p = &LAST_TASK; p > &FIRST_TASK; --p)
  if (*p)
  {
// 如果任务的alarm 时间已经过期(alarmalarm && (*p)->alarm signal |= (1 signal & ~(_BLOCKABLE & (*p)->blocked)) &&
(*p)->state == TASK_INTERRUPTIBLE)
(*p)->state = TASK_RUNNING; //置为就绪(可执行)状态。
  }

  /* this is the scheduler proper: */
  /* 这里是调度程序的主要部分 */

  while (1)
  {
  c = -1;
  next = 0;
  i = NR_TASKS;
  p = &task[NR_TASKS];
  // 这段代码也是从任务数组的最后一个任务开始循环处理,并跳过不含任务的数组槽。比较每个就绪
  // 状态任务的counter(任务运行时间的递减滴答计数)值,哪一个值大,运行时间还不长,next 就
  // 指向哪个的任务号。
  while (--i)
{
if (!*--p)
continue;
if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i;
}
  // 如果比较得出有counter 值大于0 的结果,则退出124 行开始的循环,执行任务切换(141 行)。
  if (c)
break;
  // 否则就根据每个任务的优先权值,更新每一个任务的counter 值,然后回到125 行重新比较。
  // counter 值的计算方式为counter = counter /2 + priority。[右边counter=0??]
  for (p = &LAST_TASK; p > &FIRST_TASK; --p)
if (*p)
(*p)->counter = ((*p)->counter >> 1) + (*p)->priority;
  }
  switch_to (next); // 切换到任务号为next 的任务,并运行之。
}

//// pause()系统调用。转换当前任务的状态为可中断的等待状态,并重新调度。
// 该系统调用将导致进程进入睡眠状态,直到收到一个信号。该信号用于终止进程或者使进程调用
// 一个信号捕获函数。只有当捕获了一个信号,并且信号捕获处理函数返回,pause()才会返回。
// 此时pause()返回值应该是-1,并且errno 被置为EINTR。这里还没有完全实现(直到0.95 版)。
int
sys_pause (void)
{
  current->state = TASK_INTERRUPTIBLE;
  schedule ();
  return 0;
}

// 把当前任务置为不可中断的等待状态,并让睡眠队列头的指针指向当前任务。
// 只有明确地唤醒时才会返回。该函数提供了进程与中断处理程序之间的同步机制。
// 函数参数*p 是放置等待任务的队列头指针。(参见列表后的说明)。
void
sleep_on (struct task_struct **p)
{
  struct task_struct *tmp;

  // 若指针无效,则退出。(指针所指的对象可以是NULL,但指针本身不会为0)。
  if (!p)
  return;
  if (current == &(init_task.task)) // 如果当前任务是任务0,则死机(impossible!)。
  panic ("task[0] trying to sleep");
  tmp = *p; 
  // 让tmp 指向已经在等待队列上的任务(如果有的话)。
  *p = current; 
  // 将睡眠队列头的等待指针指向当前任务。
  current->state = TASK_UNINTERRUPTIBLE; 
  // 将当前任务置为不可中断的等待状态。
  schedule (); // 重新调度。
  // 只有当这个等待任务被唤醒时,调度程序才又返回到这里,则表示进程已被明确地唤醒。
  // 既然大家都在等待同样的资源,那么在资源可用时,就有必要唤醒所有等待该资源的进程。该函数
  // 嵌套调用,也会嵌套唤醒所有等待该资源的进程。然后系统会根据这些进程的优先条件,重新调度
  // 应该由哪个进程首先使用资源。也即让这些进程竞争上岗。
  //*p=tmp; //应该加?
  if (tmp) 
  // 若还存在等待的任务,则也将其置为就绪状态(唤醒)。
  tmp->state = 0;
}

// 将当前任务置为可中断的等待状态,并放入*p 指定的等待队列中。参见列表后对sleep_on()的说明。
void
interruptible_sleep_on (struct task_struct **p)
{
  struct task_struct *tmp;

  if (!p)
  return;
  if (current == &(init_task.task))
  panic ("task[0] trying to sleep");
  tmp = *p;
  *p = current;
repeat:current->state = TASK_INTERRUPTIBLE;
  schedule ();
  // 如果等待队列中还有等待任务,并且队列头指针所指向的任务不是当前任务时,则将该等待任务置为
  // 可运行的就绪状态,并重新执行调度程序。当指针*p 所指向的不是当前任务时,表示在当前任务被放
  // 入队列后,又有新的任务被插入等待队列中,因此,既然本任务是可中断的,就应该首先执行所有
  // 其它的等待任务。
  if (*p && *p != current)
  {
  (**p).state = 0;
  goto repeat;
  }
  // 下面一句代码有误,应该是*p = tmp,让队列头指针指向其余等待任务,否则在当前任务之前插入
  // 等待队列的任务均被抹掉了。参见图4.3。
  *p = NULL;
  if (tmp)
  tmp->state = 0;
}

// 唤醒指定任务*p。
void
wake_up (struct task_struct **p)
{
  if (p && *p)
  {
  (**p).state = 0; // 置为就绪(可运行)状态。
  *p = NULL;// 去掉?   
  }
}

|
sleep_on中的*p=tmp是合理的。可以这样理解,*p代表了一个等待队列,一直指向队列的头部。其实这里有一个bug。比如,当一个进程被唤醒时马上又调用sleep_on,这时等待队列会发生混乱,引起错误。0.12内核修正了这一点。
wake_up中的*p=NULL,完全没有用。0.12内核去掉了。
可中断和不可中断确实可以在一个等待队列中,并且有信号是都会被唤醒。
但是,关键*p是什么?*p是由用户提供的结构(如buffer_head中的b_wait),所以只要用户正确的调用这两个内核函数,就不会出现上面的错误,否则由用户自己负责。

    
 
 

您可能感兴趣的文章:

  • 求助: 进程调度内核分析
  • 新人求助,进程调度的问题.
  • 回声抵消算法在LINUX ARM上跑的调度问题求助
  • 【求助】基于2.6.29内核编译的驱动程序能否应用于2.6.32内核的系统?
  • 【求助】多进程中 内核信号量无效?
  • 求助:makefile,驱动与linux内核的关系?
  • 求助,关于编译驱动进内核的一个问题,实在找不到资料了!
  • rh8编译内核出错!求助!
  • [求助]如何设置uclinux内核中的内存
  • 求助如何顺利的阅读linux内核源代码
  • 内核源码求助?
  • 求助:内核编译出错,系统不能启动!!
  • 编译内核时出现的一个问题,求助!
  • 求助:如何移植DM9000网卡驱动到linux2.6内核?
  • 想在linux下面读ntfs分区,rpm内核时出现问题,求助!
  • iptables已打入string match补丁,编译内核无法找到该项,求助高手!
  • 内核与用户进程通信得问题,求助!
  • (求助)准备向linux内核方向发展应该有哪些基础???
  • 求助: linux内核编译的问题
  • 求助!编译内核出错
  • 求助:编译新内核,怎么会影响到旧内核的声卡驱动?
  • 紧急求助内核编译问题,急求!
  • 求助一个内核模块的版本问题
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 高分求助高分求助高分求助高分求助高分求助高分求助
  • 怎样读取HZK24S前十区的内容啊???求助求助
  • 紧急求助!紧急求助!
  • 【求助】iplanet问题,求助高手解答!
  • 菜鸟求助,solaris下计算问题求助
  • 【求助】SOS紧急求助..............极为简单的问题...跪求....
  • 高分求助啊!求助SUSE 10.0 不能上网.
  • 急急急急急急急啊,紧急求助啊!!!!!满分求助啊!!!!!!
  • 求助:linux下 vim的配置(高分求助)
  • red hat怎么安装gcc啊!总是出错,求助求助啊!!!yum源怎么改啊!!
  • 求助~~求助 ~~linux文件读写问题
  • 求助:信号 --13 进程中断
  • 求助,安装了红帽子后进不了
  • 新装linux求助
  • linux的 iptables问题求助
  • (高分求助)请问,那里有软件开发的<设计文档>
  • 一个简单的问题,高分求助!!!
  • Web服务器/前端 iis7站长之家
  • VJ的一个问题,高分求助,熟悉VJ得请进!
  • 高分求助


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3