R4 Context Switch2. ¯
Linux- (context switch)
Linux-
Linux-
)c2003 ( ¯ - 4 2
3. ?
quot; - quot; ¯
¯
quot; quot;–
¯
(execution context) quot; quot; ¯
¯ ¯
, ¯ ¯ , , ,
¯
quot; ¯ – ¯
quot;
)c2003 ( ¯ - 4 3
4. Linux-
¯ Linux
.kernel mode-
,
kernel-
kernel
.user mode- ,mode
,non-preemptive Linux kernel-
:
context switch-
context switch
)c2003 ( ¯ - 4 4
5. context switch
time slice- ¯ – .1
.(scheduler_tick() )
– .2
¯, ¯ ¯ )
( ¯
¯, ¯ .3
.
.sched_yield() ¯ ¯ ¯ .4
need_resched
.user mode ,
4- 3
)c2003 ( ¯ - 4 5
6. ,Linux-
.schedule()
schedule()
.
schedule()
¯
context_switch()
.
-
,
¯
¯
)c2003 ( ¯ - 4 6
7. ,Linux-
.
:
. ¯ .1
) .2
.(
( ¯
. ¯ .3
¯ ¯ .4
.
)c2003 ( ¯ - 4 7
8. Linux-
¯ Linux-
. ¯ quot; quot; quot; quot;
–
thread
¯ ¯
¯ :User Mode-
, ¯ ,
cs, ) ¯
. ¯ ¯ ,(ds, ss, es
¯
)c2003 ( ¯ - 4 8
9. (1) Task State Segment
, ¯ Task State Segment – TSS
. ¯ ¯
. TSS Linux- ¯
(IA32)
TSS- ¯ ¯
Kernel Mode-
I/O ¯ TSS-
.init_tss ¯ ¯ TSS-
.TSS- ¯ ,
)c2003 ( ¯ - 4 9
10. (2) Task State Segment
include/asm/processor.h
struct tss_struct {
..
unsigned long esp0; ¯
(kernel mode- ¯ esp )
..
};
struct tss_struct init_tss[NR_CPUS];
)c2003 ( ¯ - 4 10
11. thread
thread_struct
:include/asm/processor.h
struct thread_struct {
unsigned long esp0; ¯
unsigned long eip; ¯
unsigned long esp; ( )
unsigned long fs;
gs- fs
unsigned long gs;
..
union i387_union i387;
..
};
)c2003 ( ¯ - 4 11
12. context_switch()
context_switch()
kernel/sched.c
switch_to ¯
. context_switch()
t t it h()
switch_to 2.4.X
inline task_t *context_switch(task_t *prev, task_t *next) {
switch_mm.... ¯
switch_to(prev, next, prev);
return prev;
}
)c2003 ( ¯ - 4 12
13. (1) switch_to
include/asm/system.h
switch_to(prev, next, last) :
, ¯ prev
, next
. ¯ last
switch_to- , 2.4.X
¯ switch_to
movl prev, %eax
movl next, %edx
pushl %esi (gcc)
¯ switch_to
pushl %edi
pushl %ebp
)c2003 ( ¯ - 4 13
14. (2) switch_to
movl %esp, prev->thread.esp – next prev
movl next->thread.esp, %esp
movl $1f, prev->thread.eip ¯ prev
¯ quot; 1quot;
pushl next->thread.eip ¯ next
jmp __switch_to __switch_to __switch_to
1:
popl %ebp
popl %edi switch_to next
popl %esi
)c2003 ( ¯ - 4 14
15. (1) __switch_to()
arch/i386/kernel/process.c
:
void FASTCALL(__switch_to(struct task_struct *prev_p,
struct task_struct *next_p));
FASTCALL
:(C ) GCC-
#define FASTCALL __attribute__(regparm(3))
( ) eax, edx, ecx 3
edx next_p- eax prev_p , ¯
? __switch_to
. , ret_from_fork –
)c2003 ( ¯ - 4 15
16. (2) __switch_to()
switch_to
¯ (context_switch() , )
. ¯
jmp __switch_to
, ¯ __switch_to()- ¯
. ¯ ret
. ¯
¯ ¯ next->thread.eip ¯
'1' ¯ , .switch_to
.context_switch() switch_to
¯ ¯ , next
.
)c2003 ( ¯ - 4 16
17. (3) __switch_to()
struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread;
struct tss_struct *tss = init_tss + smp_processor_id();
unlazy_fpu(prev_p);
tss->esp0 = next->esp0; ¯
.. TSS- ¯
movl %fs, prev->fs
movl %gs, prev->gs
if (prev->fs | prev->gs | next->fs | next->gs) {
..
movl next->fs, %fs gs- fs
movl next->gs, %gs
..
}
/* load debug registers */
/* load IO permission bitmap */
return;
)c2003 ( ¯ - 4 17
18. ....
¯ context switch
?
¯C - context switch()
context_switch()
.kernel-
, , – switch_to
.i386
. ,C – __switch_to
)c2003 ( ¯ - 4 18
19. prev
context_switch: task_struct
context_switch()
……
$1f thread.eip
esi
thread.esp
switch_to: prev edi
ebp
movl $1f, prev->thread.eip next
task_struct
context_switch()
pushl next->thread.eip
esi $1f thread.eip
__switch_to:
s tc to: edi thread.esp
thread esp
next
………
ebp
esp $1f
ret
next
context_switch()
1: esi
eip
edi
ebp
$1f
19 4 - ¯ 2003 (c)
20. User Mode
User Mode-
(2 ) Kernel Mode-
¯
quot; ss:esp
kernel
mode
eflags
¯ cs:eip
eflags
es,ds,eax,
SAVE_ALL
ebp,edi,esi,edx,
ecx,ebx
)c2003 ( ¯ - 4 20
21. Kernel Mode
?
,context_switch() ¯ switch_to
.switch_to - ebp, esi, edi
¯ switch_to- ebx – ebx
(context_switch() quot; ¯)
schedule() quot; - ecx, edx, eax
switch_to
caller- context_switch() schedule()
¯ ,(2 ¯, / ) callee
ebx, ebp, esi, edi- ¯ schedule()
.switch_to thread_struct eip- esp
¯
¯ ¯ quot; ,gs- fs
TSS thread_struct.esp0
)c2003 ( ¯ - 4 21
22. (1) Linux-
¯ ¯
(fork() ¯)
do_fork()
kernel/fork.c
do_fork()
,(file descriptors)
¯
– ¯ ¯
)c2003 ( ¯ - 4 22
23. (2) Linux-
do_fork()
copy_thread() quot;
quot; ¯
SET_LINKS quot; quot;
pid-
hash_pid()- quot;
- ¯ TASK_RUNNING
wake_up_process()- quot; runqueue
pid- do_fork() ,
,
)c2003 ( ¯ - 4 23
24. Linux-
(1) copy_thread()
¯ (arch/i386/kernel/process.c )
. thread
p
regs
kernel mode- SAVE_ALL -
¯ ¯ struct pt_regs
SAVE_ALL -
struct pt_regs* childregs;
childregs
childregs = ((struct pt_regs *)(8192 + (unsigned long) p)) – 1;
struct_cpy(childregs, regs);
fork() 0 ,2 ¯¯
childregs->eax = 0;
)c2003 ( ¯ - 4 24
25. (2) copy_thread()
p->thread.esp
p->thread.esp = (unsigned long) childregs;
p->thread.esp0
p->thread.esp0 = (unsigned long) (childregs + 1);
ret_from_fork
p->thread.eip = (unsigned long) ret_from_fork;
pushl next->thread.eip switch_to ¯
(16 ) .__switch_to
/* save fs and gs registers in thread field */
/* copy saved math regs in thread field from father to son */
)c2003 ( ¯ - 4 25
26. ret_from_fork()
¯
arch/i386/kernel/entry.S
ret_from_fork:
check need_resched
…
jmp ret_from_sys_call
ret_from_sys_call ,2 ¯
¯ user mode-
fork() ret_from_fork- ,
0
)c2003 ( ¯ - 4 26
27. ss
user - p
mode
esp
eflags task_struct
cs .
eip .
¯ eax
orig_eax .
es thread.esp0
struct pt_regs
ds ret_from_fork thread.eip
eax=0 thread.esp
ebp
SAVE_ALL
.
edi
.
esi .
edx
ecx
ebx
)c2003 ( ¯ - 4 27
28. (1)
exit() ¯ quot;
,exit()-
main() exit()-
libc ,
- __libc_start_main()
¯ main()
¯
¯,
0- ¯
-
)c2003 ( ¯ - 4 28
29. (2)
¯ do_exit()
kernel/exit.c
: ,
¯ exit_code ¯
exit() quot;
¯ ¯: ¯
init
TASK_ZOMBIE-
runqueue- ,schedule()-
.
switch_to
)c2003 ( ¯ - 4 29
30. (3)
¯
wait() ¯ ,
quot;
release_task()
kernel/exit.c
, ,
pid- (REMOVE_LINKS) ¯
,(unhash_pid())
)c2003 ( ¯ - 4 30