进程调度模块

目录

1.进程介绍


2.进程调度

2.1.进程状态

2.2.进程调度函数 ---schedule

2.3.进程切换函数 ---switch_to()


1.进程介绍

在进程模块里面,我们知道了进程就是一个task_struct的结构体,里面含有进程的各种信息。进程存放在进程数组task_struct的数组里面。

2.进程调度

在进程调度里面主要的两个函数:

//进程调度函数

        void schedule(void);

//切换到下一个进程 这个功能使用宏定义完成的
       switch_to(next);

2.1.进程状态

运行态: 可以被运行

就绪态: 进程切换时,只能在就绪态里面挑选进程

可中断睡眠状态: 可以被信号打断,变成就绪态或者运行态

不可中断睡眠状态: 只能被wakeup所唤醒变成就绪态或者运行态

暂停状态: 收到SIGTOP,SIGTSTP,SIGTTIN

僵死状态: 进程停止运行,但是父进程没有回收,  waitpid函数。

2.2.进程调度函数 ---schedule

1. 检查所有进程的定时器,然后唤醒某一些进程,将进程从可中断睡眠状态变为就绪态

2.循环task列表 根据counter大小决定进程切换

       (1)如果找到最大值,而且不为0,直接返回,没有(2)了。

        (2)如果都为0,进行时间片的重新分配,然后重新执行2步骤。

3.切换到下一个进程------switch_to函数

// 时间片分配
void schedule(void)
{
	int i,next,c;
	struct task_struct ** p;

/* check alarm, wake up any interruptible tasks that have got a signal */

	for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
		if (*p) {//alarm是用来设置警告,比如jiffies有1000个可能其中一些需要警告那么就用alarm来实现
			if ((*p)->alarm && (*p)->alarm < jiffies) {
					(*p)->signal |= (1<<(SIGALRM-1));
					(*p)->alarm = 0;
				}
				//~(_BLOCKABLE & (*p)->blocked  
				//&&(*p)->state==TASK_INTERRUPTIBLE
				//用来排除非阻塞信号
				//如果该进程为可中断睡眠状态 则如果该进程有非屏蔽信号出现就将该进程的状态设置为running
			if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
			(*p)->state==TASK_INTERRUPTIBLE)
				(*p)->state=TASK_RUNNING;
		}

/* this is the scheduler proper: */
	// 以下思路,循环task列表 根据counter大小决定进程切换
	while (1) {
		c = -1;
		next = 0;
		i = NR_TASKS;
		p = &task[NR_TASKS];
		while (--i) {
			if (!*--p)
				continue;//进程为空就继续循环
			if ((*p)->state == TASK_RUNNING && (*p)->counter > c)//找出c最大的task
				c = (*p)->counter, next = i;
		}
		if (c) break;//如果c找到了,就终结循环,说明找到了
		//进行时间片的重新分配
		for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
			if (*p)//这里很关键,在低版本内核中,是进行优先级时间片轮转分配,这里搞清楚了优先级和时间片的关系
			//counter = counter/2 + priority
				(*p)->counter = ((*p)->counter >> 1) +
						(*p)->priority;
	}
	//切换到下一个进程 这个功能使用宏定义完成的
	switch_to(next);
}

  2.3.进程切换函数 ---switch_to()

 1.先判断是否为当前进程,如果是,不用切换

2.切换进程:

        (1)将进程赋值给全局变量current这个变量,就可以完成进程切换

        (2)将进程的上下文(TSS和当前堆栈中的信息)切换

// 进程切换是用汇编宏定义实现的
//1. 将需要切换的进程赋值给当前进程的指针
//2. 将进程的上下文(TSS和当前堆栈中的信息)切换
#define switch_to(n) {\
struct {long a,b;} __tmp; \
__asm__("cmpl %%ecx,_current\n\t" \
	"je 1f\n\t" \
	"movw %%dx,%1\n\t" \
	"xchgl %%ecx,_current\n\t" \
	"ljmp %0\n\t" \
	"cmpl %%ecx,_last_task_used_math\n\t" \
	"jne 1f\n\t" \
	"clts\n" \
	"1:" \
	::"m" (*&__tmp.a),"m" (*&__tmp.b), \
	"d" (_TSS(n)),"c" ((long) task[n])); \
}

 3.sleep_on函数

当某个进程想访问CPU资源,但是CPU资源被占用访问不到,就会休眠。休眠是以链表形成的,类似递归的情况。-----sleep等待队列

 

// 当某个进程想访问CPU资源,但是CPU资源被占用访问不到,就会休眠
void sleep_on(struct task_struct **p)
{
	struct task_struct *tmp;

	if (!p)//如果传进来的是空的 就返回
		return;
	if (current == &(init_task.task))//当前进程是0号 
		panic("task[0] trying to sleep");//就打印并且返回
	tmp = *p;
	*p = current;//这两步相当于 给休眠链表添加了一个新node
	// 其实核心就是把state置为TASK_UNINTERRUPTIBLE
	current->state = TASK_UNINTERRUPTIBLE;
	schedule();
	if (tmp)
		tmp->state=0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值