Linux进程调度及初始化(0.11版本源码分析)

进程调度:

创建进程时,进程调度类的初始化在函数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;      //程序状态段 

猜你喜欢

转载自blog.csdn.net/m0_37806112/article/details/80381182