进程调度:
创建进程时,进程调度类的初始化在函数sched_init()进行
void sched_init(void) { int i; struct desc_struct * p; if (sizeof(struct sigaction) != 16) panic("Struct sigaction MUST be 16 bytes"); //设置内核的局部状态 描述符和程序状态段 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); //偏移量 p = gdt+2+FIRST_TSS_ENTRY; //清空整个全局的task struct 结构体指针数组 for(i=1;i<NR_TASKS;i++) { task[i] = NULL; //清空task列表 //清空GDT p->a=p->b=0; p++; p->a=p->b=0; p++; } /* Clear NT, so that we won't have troubles with that later on */ __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); //设置cms ltr(0); lldt(0); outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ //开启系统时钟中断 set_intr_gate(0x20,&timer_interrupt); outb(inb_p(0x21)&~0x01,0x21); //开启系统调用 设置中断函数 set_system_gate(0x80,&system_call); }
相当于把进程看成一个一个链表结点。
进程创建:
- 首先我们先创建0号进程,0号进程是所有进程的父进程。(main.c/init())
void init(void) { int pid,i; //运行setup.s程序,进行配置 //获取由setup程序进行解析的参数 setup((void *) &drive_info); //open标准输入的文件句柄 (void) open("/dev/tty0",O_RDWR,0); //打开标准输入控制台 (void) dup(0); //打开标准输出控制台 (void) dup(0); //打开标准错误控制台 //make mkdir("/proc",755); mknod("/proc/sysinfo", S_IFPROC,8 ); printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS, NR_BUFFERS*BLOCK_SIZE); printf("Free mem: %d bytes\n\r",memory_end-main_memory_start); //创建1号进程 if (!(pid=fork())) { close(0); if (open("/etc/rc",O_RDONLY,0)) _exit(1); execve("/bin/sh",argv_rc,envp_rc); _exit(2); }
init()函数概述:
1.打开标准输入 输出 错误的控制台句柄
2.创建1号进程,如果创建成功,则在一号进程中首先打开了 "/etc/rc"文件 (配置文件)执行SHELL程序 "/bin/sh"
注意:0号进程是不可能结束的,它会在没有其他进程调用的时候,只执行for(;;) pause();
- 在tack链表中找一个进程空位存放当前进程 (fork.c) ,返回一个进程号
int find_empty_process(void) { int i; repeat: if ((++last_pid)<0) last_pid=1; for(i=0 ; i<NR_TASKS ; i++) if (task[i] && task[i]->pid == last_pid) goto repeat; for(i=1 ; i<NR_TASKS ; i++) if (!task[i]) return i; return -EAGAIN; }
- 创建一个子进程的task_struct结构体
//为task_struct分配一片内存 p = (struct task_struct *) get_free_page(); if (!p) return -EAGAIN;
- 将当前的子进程放入到整体进程链表中
task[nr] = p;
- 设置当前的task_struct结构体
//设置分配好并且添加到全局task数组中的task_struct 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; //设置TSS段,程序运行时CPU中寄存器的值 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__("clts ; fnsave %0"::"m" (p->tss.i387));对于一个进程我们可以把它看成有三大部分组成
task_struct结构体详细介绍:
long state; //进程运行的状态 TASK_RUNNING 0 运行态 TASK_INTERRUPTIBLE 1 可中断状态 TASK_UNINTERRUPTIBLE 2 不可中断状态 TASK_ZOMBIE 3 僵尸状态 TASK_STOPPED 4 停止状态 long counter;//进程的执行时间片,表示当前进程能够占用CPU资源的时间 long priority;//进程优先级 long signal; //信号量位图 32bit每一个bit来表示一个信号 struct sigaction sigaction[32];//信号量 long blocked; /* bitmap of masked signals */ //信号掩码 /* various fields */ int exit_code; //退出码 unsigned long start_code,end_code,end_data,brk,start_stack; //当前进程的内存使用信息 long pid,father,pgrp,session,leader;//father pid unsigned short uid,euid,suid;//进程的用户ID 进程的有效ID 进程的超级ID unsigned short gid,egid,sgid;//进程的组ID 进程的有效组ID 进程的超级组ID long alarm; //进程的警告标志 long utime,stime,cutime,cstime,start_time;//有关进程的用户时间 系统时间 当前用户时间 当前系统时间 开始时间 unsigned short used_math;//是否使用协处理器 /* file system info */ int tty; /* -1 if no tty, so it must be signed *///当前进程是否占用控制台 unsigned short umask; //用户的掩码 struct m_inode * pwd; //路径 struct m_inode * root; //根目录 struct m_inode * executable;//执行位图 unsigned long close_on_exec;//执行结束后时候关闭位图 struct file * filp[NR_OPEN];//当前进程的文件表 FD在这个数组中找到一个file结构体 /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */ struct desc_struct ldt[3]; //局部描述符表由代码段和数据段组成 /* tss for this task */ struct tss_struct tss; //程序状态段