转载自https://www.lanqiao.cn/courses/reports/1420124/
1 在 kernel/.sched.c 中修改
在适当位置定义全局变量 tss
/* start */
struct tss_struct *tss = &(init_task.task.tss);
/* end */
修改 schedule() 函数中的 switch_to() 调用:
switch_to(task[next],_LDT(next));
2 在 include/linux/sched.h 中修改
在头部声明两个函数
/* add */
void switch_to(struct task_struct *, int);
void first_return_from_kernel();
/* end */
在 struct task_struct 结构体增加变量 kernelstack,这里增加到第四行,也就是李治军老师说的位置12
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
long kernelstack;
long signal;
将原来的#define INIT_TASK
/* state etc / { 0,15,15,
/ signals / 0,{{},},0,
更改为#define INIT_TASK
/ state etc / { 0,15,15,PAGE_SIZE+(long)&init_task ,
/ signals */ 0,{{},},0, \
最后要将 switch_to 的宏实现注释掉
3 增加和修改硬编码,主要是我们在 task_struct 中增加了一个变量,因此需要改变这里变量的位置,修改kernel/system_call.s
ESP0 = 4
state = 0 # these are offsets into the task-struct.
counter = 4
priority = 8
KERNEL_STACK = 12
signal = 12 + 4
sigaction = 16 + 4 # MUST be 16 (=len of sigaction)
blocked = (33*16 + 4)
增加全局标识符,使汇编函数变成全局函数
.globl first_return_from_kernel,switch_to
增加 switch_to 和 first_return_from_kernel 的实现
switch_to:
pushl %ebp
movl %esp,%ebp
pushl %ecx
pushl %ebx
pushl %eax
pushl %es
pushl %gs
pushl %esi
pushl %edi
pushl %edx
movl 8(%ebp),%ebx
cmpl %ebx,current
je 1f
# Switch PCB
movl %ebx,%eax
xchgl %eax,current
# Overrides of kernel stack pointers in TSS
movl tss,%ecx
addl $4096,%ebx
movl %ebx,ESP0(%ecx)
# Switch kernel stack
movl %esp,KERNEL_STACK(%eax)
movl 8(%ebp),%ebx
movl KERNEL_STACK(%ebx),%esp
# Switch LDT
movl 12(%ebp),%ecx
lldt %cx
movl $0x17,%ecx
mov %cx,%fs
cmpl %eax,last_task_used_math
jne 1f
clts
1: popl %edx
popl %edi
popl %esi
popl %gs
popl %es
popl %eax
popl %ebx
popl %ecx
popl %ebp
ret
first_return_from_kernel:
popl %edx
popl %edi
popl %esi
pop %gs
pop %fs
pop %es
pop %ds
iret
4 修改fork.c 同样,这里需要将一些栈添加进去:
这里修改copy_process函数。第一,添加变量krnstack;第二,krnstack指向一些栈。以下为修改后的copy_process。
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)
{
struct task_struct *p;
int i;
struct file *f;
long *krnstack;
p = (struct task_struct *) get_free_page();
if (!p)
return -EAGAIN;
task[nr] = p;
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE;
p->pid = last_pid;
p->father = current->pid;
p->counter = p->priority;
p->signal = 0;
p->alarm = 0;
p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
p->start_time = jiffies;
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (p->tss.i387));
if (copy_mem(nr,p)) {
task[nr] = NULL;
free_page((long) p);
return -EAGAIN;
}
krnstack = (long*)(PAGE_SIZE + (long)p);//stack pionter
*(--krnstack) = ss & 0xffff;
*(--krnstack) = esp;
*(--krnstack) = eflags;
*(--krnstack) = cs & 0xffff;
*(--krnstack) = eip;
// stack for schedule
*(--krnstack) = ds & 0xffff;
*(--krnstack) = es & 0xffff;
*(--krnstack) = fs & 0xffff;
*(--krnstack) = gs & 0xffff;
*(--krnstack) = esi;
*(--krnstack) = edi;
*(--krnstack) = edx;
*(--krnstack) = first_return_from_kernel;
*(--krnstack) = ebp;
*(--krnstack) = ecx;
*(--krnstack) = ebx;
*(--krnstack) = 0; //0 for res
*(--krnstack) = es;
*(--krnstack) = gs;
*(--krnstack) = esi;
*(--krnstack) = edi;
*(--krnstack) = edx;
p->kernelstack = krnstack;
for (i=0; i<NR_OPEN;i++)
if ((f=p->filp[i]))
f->f_count++;
if (current->pwd)
current->pwd->i_count++;
if (current->root)
current->root->i_count++;
if (current->executable)
current->executable->i_count++;
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
p->state = TASK_RUNNING; /* do this last, just in case */
return last_pid;
}