task_struct
1.进程的状态
分时技术进行多进程调度
重点:进程的创建是如何的?
linux在初始化的过程中那个会进行0号进程的创建,fork
sched_init(); 做了什么
内核态 不可抢占
用户态 可以抢占
move_to_user_mode(); 把内核状态切换到用户态
在内核初始化的过程中,会手动创建0号进程,0号进程是所有进程的父进程
进程初始化:
在o号进程中:
1.打开标准输入、输出、错误控制台句柄
2.创建1号进程,如果创建成功,则在1号进程中
首先打开"/etc/rc"文件
执行SHELL程序"/bin/sh"
3.0号进程不可能结束,他会在没有其他进程调用时运行,只会执行for(;;) pause();
进程创建:
fork
1.在task链表中找一个空位存放进程
2.创建一个task_struct
3.设置task_struct
进程的创建就是对0号进程或者当前进程的复制
0号进程复制 结构体的复制 把task[0]对应的task_struct复制给新创建的task_struct
对于栈堆的拷贝 当进程创建的时候要复制原有栈堆(复制完清空)
进程的创建是系统调用:
.align 2
_sys_fork:
call _find_empty_process
testl %eax,%eax
js 1f
push %gs
pushl %esi
pushl %edi
pushl %ebp
pushl %eax
call _copy_process
addl $20,%esp
1: ret
1.给当前要创建的进程分配一个进程号:find_empty_process
2.进程创建主体copy_process,为子进程创建一个task_struct结构体
struct task_struct *p;
p = (struct task_struct *) get_free_page();
3.将当前子进程放入到整体进程链表中
task[nr] = p;
4.设置创建的task_struct
p->state = TASK_RUNNING;
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;
p->tss.back_link = 0;
p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10;
p->tss.eip = eip;
p->tss.eflags = eflags;
p->tss.eax = 0;
p->tss.ecx = ecx;
p->tss.edx = edx;
p->tss.ebx = ebx;
p->tss.esp = esp;
p->tss.ebp = ebp;
p->tss.esi = esi;
p->tss.edi = edi;
p->tss.es = es & 0xffff;
p->tss.cs = cs & 0xffff;
p->tss.ss = ss & 0xffff;
p->tss.ds = ds & 0xffff;
p->tss.fs = fs & 0xffff;
p->tss.gs = gs & 0xffff;
p->tss.ldt = _LDT(nr);
p->tss.trace_bitmap = 0x80000000;
如果当前进程使用了协处理器,那就设置协处理器
if (last_task_used_math == current)
asm("fnsave %0"::"m" (p->tss.i387));
进行老进程向新进程代码段 数据段(LDT)的拷贝
if (copy_mem(nr,p)) {
free_page((long) p);
return -EAGAIN;
}
如果父进程打开了某个文件,那么子进程也同样打开这个文件,所以讲文件打开计数+1
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++;
设置进程的两个段,并结合上文设置的变量,组合成一个进程
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
返回创建的进程id
return last_pid;