Reputation: 361
I'm currently learning linux kernel source code (v0.11). The following is the main()
function of init/main.c
:
void main(void)
{
...
move_to_user_mode();
if (!fork()) { /* we count on this going ok */
init();
}
where in move_to_user_mode
, process 0 goes to user mode by doing this:
#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %%eax\n\t" \
"pushfl\n\t" \
"pushl $0x0f\n\t" \
"pushl $1f\n\t" \
"iret\n" \
"1:\tmovl $0x17,%%eax\n\t" \
"movw %%ax,%%ds\n\t" \
"movw %%ax,%%es\n\t" \
"movw %%ax,%%fs\n\t" \
"movw %%ax,%%gs" \
:::"ax")
After iret
, it seems like that the user mode ss:esp
points to the same stack as it is in kernel mode. i.e. p0's user stack = p0's kernel stack. Is this true?
When p0 calls fork
, it calls copy_process
, which copies its user mode ss:esp
to p1's tss->ss
and tss->esp
. So will p1 share the same user mode stack as p0? If so, p1's user stack = p0's user stack = p0's kernel stack. Will this cause any problem?
The copy_process
is as following:
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
long ebx,long ecx,long edx,
long fs,long es,long ds,
long eip,long cs,long eflags,long esp,long ss)
{
...
p->tss.esp = esp;
...
p->tss.ss = ss & 0xffff;
...
}
P.S. p0's kernel stack is below LOW_MEMORY, which means it does not support COW.
Upvotes: 4
Views: 291
Reputation: 361
p0's user stack is the user_stack
defined in kernel/sched.c
, which is the same stack used before move_to_user_mode
, and which is the value of the pushed esp
in move_to_user_mode
. And after move_to_user_mode
, p0 should not use this space (this is why the following fork
and pause
are inline function) since p1's user stack also points to this space when p0 calls fork
to produce p1. This space is set to read-only in p1's page table. When p1 wants to use this space, it will trigger a page fault, and then trigger COW for this space, i.e. the kernel will allocate a new page for p1's stack.
Conclusion:
p0's user stack = p1's user stack right after fork
.
p0 does not use its user stack.
p1 will trigger COW on this stack space when it wants to write to the stack.
Upvotes: 3