好文档 - 专业文书写作范文服务资料分享网站

(VR虚拟现实技术)L进程调度切换和虚拟空间管理深入分析最全版

天下 分享 时间: 加入收藏 我要投稿 点赞

6) 将next->thread.eip的指针内容压到next的内核态堆栈中,通常它的内容也是Label 1。 pushl 480(íx)

7) 跳转到__switch_to()C函数执行。 jmp __switch_to

8) 被替换的进程A继续执行,它在Label 1处,首先是恢复eflags和ebp寄存器内容。注意这里是发生在调度器选择prev在CPU上运行后,次数esp已经执行了prev的内核堆栈。 1:

popl ?p popfl

9) 将eax内容保存到last任务结构中。这里eax是被进程A切换下来的进程C的task结构指针。 movl êx, last

5.__switch_to深入分析

__switch_to参数是存放在eax和edx中的内容,这通过

#define fastcall __attribute__((regparm(3)))告诉gcc编译器。 1) 获取tss_struct tss、prev_p和next_p的thread_struct结构prev和next、当前CPU逻辑ID。

2) 调用__unlazy_fpu(prev_p)根据条件标志选择是否保存prev_p的FPU, MMX, 和XMM寄存器内容。

3) load_esp0(tss, next)将next的堆栈地址存放到tss中:tss->esp0 = thread->esp0。

4) savesegment(gs, prev->gs)保存gs寄存器到prev->gs,fs已经在栈入口保存,es和ds在内核态下不需要保存。

5) load_TLS(next, cpu)从next的tls_array 缓存中加载线程的Thread-Local Storage描述符。TLS在GDT表中位置6、7、8。 cpu_gdt_table[cpu][6] = next_p->thread.tls_array[0]; cpu_gdt_table[cpu][7] = next_p->thread.tls_array[1]; cpu_gdt_table[cpu][8] = next_p->thread.tls_array[2];

6) 如果当前特权级别是0并且prev->iopl != next->iopl则恢复IOPL设置set_iopl_mask(next->iopl)。

7) 根据thread_info的TIF标志_TIF_WORK_CTXSW和TIF_IO_BITMAP判断是否需要处理debug寄存器和IO位图:__switch_to_xtra(next_p, tss); l 只有当next_p挂起时即if (test_tsk_thread_flag(next_p, TIF_DEBUG))使用了debug寄存器才需要恢复set_debugreg(next->debugreg[i], i)。只有调试器需要监控prev的状态时,prev_p->thread.debugreg数组的内容才会被修改。Debug寄存器dr0~dr7,dr4和dr5不用。

l 当prev_p或者next_p定义了自己的I/O访问位图时,必须更新TSS的I/O bitmap。

if (prev_p->thread.io_bitmap_ptr || next_p->thread.io_bitmap_ptr) handle_io_bitmap(&next_p->thread, &init_tss[cpu]);

进程的I/O访问位图存放在io_bitmap_ptr指针里,通常进程很少修改IO位图,只有当前时间片中访问IO端口才会把实际的IO位图加载到TSS中。 ü 当next_p没有自定义位图时:

tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; 返回 ü 如果next == tss->io_bitmap_owner则设置有效的偏移量:tss->io_bitmap_base = IO_BITMAP_OFFSET; 返回

ü 否则tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; 只有第二种情况tss->io_bitmap_base设置的是有效的io_bitmap偏移量,对于其他两种情况,当用户进程访问I/O端口时将会触发\的异常,do_general_protection( )异常处理函数根据io_bitmap的值处理异常:如果是0x8000(INVALID_IO_BITMAP_OFFSET)则发送SIGSEGV信号给用户进程;如果是0x9000(INVALID_IO_BITMAP_OFFSET_LAZY)则拷贝进程的thread中的io_bitmap_ptr内容到io_bitmap中,并设置io_bitmap_base为正确的偏移量(104)。

8) disable_tsc(prev_p, next_p)设置cr4中的TSC Disable位。 9) arch_leave_lazy_cpu_mode()设置CPU的lazy模式。

10) 如果next_p->fpu_counter > 5则恢复next_p的FPU寄存器内容: math_state_restore()。FPU寄存器存放在next_p->thread->i387中,i387是i387_union的union结构: union i387_union {

struct i387_fsave_struct fsave; struct i387_fxsave_struct fxsave; struct i387_soft_struct soft; };

struct i387_fxsave_struct { unsigned short cwd;

unsigned short swd; unsigned short twd; unsigned short fop; long fip; long fcs; long foo; long fos; long mxcsr; long mxcsr_mask;

long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ long padding[56];

} __attribute__ ((aligned (16)));

11) 如果需要,则从next->gs中恢复gs寄存器内容。 if (prev->gs | next->gs)

loadsegment(gs, next->gs);

二、Linux实时调度schedule

1.概述

三种调度策略:SCHED_FIFO,SCHED_RR和SCHED_NORMAL。

FIFO实时调度算法当调度器将CPU指定给某个进程时,它把该进程放到运行队列首;除非有更高优先级的进程,否则该进程将一直占用CPU。

Round Robin实时进程调度把CPU指定给某进程,把它放到运行队列尾。时间片运行完再选择其他进程调度。这样保证了同优先级的公平竞争CPU。 SCHED_NORMAL是普通的基于运行时间和等待时间等,动态调整进程优先级的一种调度策略。

实时进程优先级1~100,普通101~139。

2.实时进程调度的时机

1) 该进程被更高优先级的进程抢占;

2) 进程执行一个阻塞操作,被放到睡眠队列,状态为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE;

3) 进程被终止(状态为TASK_STOPPED 或TASK_TRACED),或者进程被杀死(状态为EXIT_ZOMBIE 或 EXIT_DEAD) 4) 进程调用sched_yield()主动放弃CPU; 5) RR实时进程用完了CPU分配的时间片;

3.调度器相关函数

1) scheduler_tick( )

更新当前进程的运行时间片tick值,在update_process_times( )中调用,判断进程的时间片是否用完。

2) try_to_wake_up( )

唤醒一个睡眠的进程并把它的状态设为TASK_RUNNING,插入到运行队列中。

3) recalc_task_prio( )

(VR虚拟现实技术)L进程调度切换和虚拟空间管理深入分析最全版

6)将next->thread.eip的指针内容压到next的内核态堆栈中,通常它的内容也是Label1。pushl480(íx)7)跳转到__switch_to()C函数执行。jmp__switch_to8)被替换的进程A继续执行,它在Label1处,首先是恢复eflags和ebp寄存器内容。注意
推荐度:
点击下载文档文档为doc格式
5doo44si4f9epjx24qwd4i6jo0x1m7012b9
领取福利

微信扫码领取福利

微信扫码分享