task_struct
counter = counter/2 + priority
1.进程的状态
分时技术进行多进程调度
重点:进程的创建是如何的?
1.Linux在初始化的过程中会进行0号进程的创建,fork()
sched_init(); 做了什么事情?
内核态:不可抢占的
用户态:可以抢占的
move_to_user_mode(); 把内核状态从内核态切换到用户态
在内核的初始化过程中,会手动创建0号进程,0号进程是所有进程的父进程
进程的初始化:
在0号进程中:
1.打开标准 输入 输出 错误 的控制台句柄
2.创建1号进程,如果创建成功,则在1号进程中:
(1)首先打开了“/etc/rc”文件
(2)执行SHELL程序“/bin/sh”
3.0号进程不可能结束,他会在没有其他进程调用的时候调用,只会执行
for(;;),pause();
2.进程创建
fork():
1.在task链表中找一个进程空位存放当前的进程
2.创建一个task_struct
3.设置task_struct
进程的创建就是对0号进程或者当前进程的复制
0号进程复制-结构体的复制-把task[0]对应的task_struct复制给新创建的task_struct
对于堆栈的拷贝-当进程做创建的时候要复制原有的堆栈
1.进程的创建时系统调用:
sys_fork()调用,用于创建子进程,是system_call 功能2。原形在include/linux/sys.h 中。
// 首先调用C 函数find_empty_process(),取得一个进程号pid。若返回负数则说明目前任务数组
// 已满。然后调用copy_process()复制进程。
align 4
_sys_fork:
call _find_empty_process ;// 调用find_empty_process()(kernel/fork.c,135)。
test eax,eax
js l2
push gs
push esi
push edi
push ebp
push eax
call _copy_process ;// 调用C 函数copy_process()(kernel/fork.c,68)。
add esp,20 ;// 丢弃这里所有压栈内容。
l2: ret
(1)给当前要创建的进程分配一个进程号。find_empty_process
(2)创建一个子进程的task_struct结构体:
struct task_struct *p;
p = (struct task_struct *)get_free_page();
struct task_struct *p;
p = (struct task_struct *)kmalloc(sizeof(task_struct));
(3)将当前的子进程放入到整体进程链表当中
task[nr] = p;
(4)设置创建的task_struct结构体,如果当前进程使用了协处理器,那就设置当前创建进程的协处理器
if (last_task_used_math == current)
__asm__ ("frstor %0"::"m" (current->tss.i387));
int copy_mem(int nr, struct task_struct * p)
进行老进程向新进程代码段与数据段(及LDT)的拷贝
如果父进程打开了某个文件,那么子进程也同样打开了这个文件,所以将文件的打开计数+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++;
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*/
返回新创建进程的PID
return last_pid;