• 内核进程的调度与进程切换


    进程被创建到了链表中,如何再进行进一步的调用和调用?

    进程调度

            void schedule(void);        进程调度

            switch_to(next);        进程切换函数

    1. void schedule(void)
    2. {
    3. int i,next,c;
    4. struct task_struct ** p;
    5. /* check alarm, wake up any interruptible tasks that have got a signal */
    6. for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
    7. if (*p) {
    8. if ((*p)->alarm && (*p)->alarm < jiffies) {
    9. (*p)->signal |= (1<<(SIGALRM-1));
    10. (*p)->alarm = 0;
    11. }
    12. //信号不为空,并且去除不能引发进程就绪状态的阻塞信号,且现在进程为可中断状态
    13. if ((*p)->signal && (*p)->state==TASK_INTERRUPTIBLE)
    14. (*p)->state=TASK_RUNNING;
    15. }
    16. /* this is the scheduler proper: */
    17. while (1) {
    18. c = -1;
    19. next = 0;
    20. i = NR_TASKS;
    21. p = &task[NR_TASKS];
    22. while (--i) {
    23. if (!*--p)
    24. continue;
    25. //找到当前counter最大值
    26. if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
    27. c = (*p)->counter, next = i;
    28. }
    29. if (c) break;
    30. //如果task链表中所有进程的时间片为0,则进行时间片重分配
    31. for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
    32. if (*p)
    33. (*p)->counter = ((*p)->counter >> 1) +
    34. (*p)->priority; //counter = counter/2+pri
    35. }
    36. switch_to(next);
    37. }

    进程状态

    运行状态                           #define TASK_RUNNING        0  可以被运行,就绪状态,只有这种状态才能被运行

    可中断睡眠状态                 #define TASK_INTERRUPTIBLE  1  可以被信号中断,使其变成RUNING

    不可中断睡眠状态             #define TASK_UNINTERRUPTIBLE    2  只能被wakeup唤醒变成RUNNING

    暂停状态                           #define TASK_STOPPED        4   被相关STOP信号暂停

    僵死状态                          #define TASK_ZOMBIE     3   进程停止运行,但是没有被父进程进行回收

    进程切换:

    将进程切换为当前执行进程

    1.将需要切换的进程赋值给当前执行进程

    2.切换进程上下文(TSS等信息),堆栈信息

    1. #define switch_to(n) {\
    2. struct {long a,b;} __tmp; \
    3. __asm__("cmpl %%ecx,_current\n\t" \ //比较一下是否为当前进程
    4. "je 1f\n\t" \
    5. "xchgl %%ecx,_current\n\t" \
    6. "movw %%dx,%1\n\t" \
    7. "ljmp %0\n\t" \
    8. "cmpl %%ecx,%2\n\t" \
    9. "jne 1f\n\t" \
    10. "clts\n" \
    11. "1:" \
    12. ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
    13. "m" (last_task_used_math),"d" _TSS(n),"c" ((long) task[n])); \
    14. }

    进程睡眠函数

    1. void sleep_on(struct task_struct **p)
    2. {
    3. struct task_struct *tmp;
    4. if (!p)
    5. return;
    6. if (current == &(init_task.task))
    7. panic("task[0] trying to sleep");
    8. tmp = *p;
    9. *p = current;
    10. current->state = TASK_UNINTERRUPTIBLE;
    11. schedule();
    12. if (tmp)
    13. tmp->state=0;
    14. }

  • 相关阅读:
    C++学习笔记02-面向对象及类的引入
    【spring源码系列】之【FactoryBean类型的接口】
    头歌实验Java生成验证码
    【无标题】
    [OC学习笔记]Block三种类型
    藏宝计划TreasureProject(TPC)系统模式开发技术原理
    iNFTnews | web3将如何改变创作者经济?
    三门问题的 Python 实验数据 & 直观但非严谨的证明
    KMP算法
    mac里提示‘.bash_profile’: not a valid identifier 该怎么处理
  • 原文地址:https://blog.csdn.net/weixin_66218530/article/details/134055265