《Linux内核分析》MOOC课程之从迷你Linux内核角度理解进程时间轮片调度(未完)



代码分析

  1. mypcb.h

    技术分享

  2. mymain.c

    技术分享

    上面这段代码主要完成了对0号进程的初始化,即pid置为0,状态state置为0(即runnable状态),进程入口及当前进程的线程的ip指向my_process,线程的sp指向当前进程的进程堆栈,由于目前只有0号进程,所以next指针指向自己形成一个单PCB链表。技术分享

    上面这段代码主要是扩充循环链表,使用memcpy()复制0号进程的状态给创建的从1号到MAX_TASK_NUM-1号进程,并与0号进程一起构成一个循环PCB链表。

    技术分享

    上面这段代码功能是从循环PCB链表的task[0]启动0号进程,是通过使用了gcc的内联汇编来实现的。接下来我们具体分析该过程:

    初始堆栈状态:

    技术分享

    movl %1, %%esp

    技术分享

    push1 %1

    技术分享

    pushl %0

    技术分享

    ret

    技术分享

    popl %%ebp

    技术分享

    其实这段汇编代码是不会被执行的,因为ret \n\t后eip指向了0号进程的起始地址。

    技术分享

    上面这段代码实现每循环1千万次打印一下当前进程的pid,然后判断时钟中断是否将调度标志(my_need_sched)置为1,如果是1则将调度标志置为0,调用my_schedule(),避免消息机制,然后再打印一次当前进程的pid。

  3. myinterrupt.c

    技术分享

    my_time_handler()实现被调用每千次且调度标志(my_need_sched)不为1时,打印“>>>my_timer_handler here<<<”且将调度标志置为1,以便于my_schedule()在my_process()中可被调用。

    技术分享

    上面这段代码为进程调度函数容错处理及next和prev指针的定义与初始化。

    假设现在0号进程正在运行,而1号进程为unrunnable状态即next->state为-1,则进入创建进程分支:

    技术分享

    先将next->state置为0,指向下一进程,打印进程切换关系,然后执行汇编内容,从堆栈角度分析该内联汇编执行过程:

    堆栈初始状态

    技术分享

    pushl %%ebp

    技术分享

    movl %%esp, %0

    技术分享

    movl %%2, %%esp

    movl %%2, %%ebp

    技术分享

    movl $1f, %1

    pushl %3

    技术分享

    ret

    技术分享

技术分享

上面这段代码功能为,如果当前进程所在PCB循环链表的下一个结点的状态state的值为零即下一进程状态为runnable时,切换到下一进程,再打印下切换关系。具体的上下文切换过程用gcc内联汇编写的,下面来通过图片分析:

寄存器初始状态

……

未完,待续



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。