第24章 任务中定时器的设计与实现
来源:互联网 发布:mac装win10会毁电脑吗 编辑:程序博客网 时间:2024/06/07 10:31
目标:实现定时器功能,实现系统调用sleep。
定时器的定义如下所示,系统使用定时器链表管理定时器。
struct timer{ struct task_struct *task; struct timer *next, *prev; int time_slice;};struct timer_list{ unsigned long timer_nr; struct timer *head, *tail;};
任务调用sleep(int ms)函数时,会在定时器链表上插入一个定时器,然后任务挂起。每次时钟中断,内核都会检查定时器链表上的定时器,假如定时器到点,则删除定时器,并唤醒与该定时器关联的任务。定时器插入算法就是遍历链表,算法复杂度为O(n)。定时器检查算法的复杂度为O(1)。
假设
任务A睡20秒
任务B睡5秒
任务C睡9秒
任务D睡2秒
任务E睡14秒
任务F睡40秒
任务 DBCEAF时刻0259142040定时器的时间长度值 2345620也就是在定时器链表上,第1个定时器的时间值是2秒,对应的任务是D;第2个定时器的时间值是3秒,对应的任务是B;
定时器插入函数如下所示
//把定时器插入到定时器链表中//每个定时器代表一段距离,表示离左边定时器的时间片距离struct timer * add_timer(struct timer *t){ if(!t) return NULL; //当定时器链表为空时 if(task_timer_list.head == NULL) { task_timer_list.head = task_timer_list.tail = t; ++task_timer_list.timer_nr; return t; } //当定时器不为空时 struct timer *p = NULL; p = task_timer_list.head; while(p && p->time_slice <= t->time_slice) { t->time_slice -= p->time_slice; p = p->next; } if(p == task_timer_list.head) //插在最前面 { p->time_slice -= t->time_slice; p->prev = t; t->next = p; t->prev = NULL; task_timer_list.head = t; } else if(p == NULL) //插在最后面 { task_timer_list.tail->next = t; t->prev = task_timer_list.tail; t->next = NULL; task_timer_list.tail = t; } else //插在中间 { p->time_slice -= t->time_slice; p->prev->next = t; t->next = p; t->prev = p->prev; p->prev = t; } ++task_timer_list.timer_nr; return t;}
定时器检查函数如下所示
void check_timer(){ struct timer *p = NULL , *tmp = NULL; p = task_timer_list.head; //检查定时器链表 if(p) //链表上有定时器 { //定时器到点 if(--(p->time_slice) == 0) { //可能有多个定时器到点 while(p && p->time_slice == 0) { if(p->next == NULL) //只剩下一个定时器 { task_timer_list.head = task_timer_list.tail = NULL; } else //剩下多个定时器 { task_timer_list.head = p->next; task_timer_list.head->prev = NULL; } //定时器的任务为空可能是因为该任务已被删除(sys_remove_task) //定时器指定的任务有可能已经被其他任务唤醒了(使用resume_task系统调用) if(p->task && p->task->state == TASK_STATE_SUSPEND) { //从挂起队列中移除任务 remove_task_from_suspend(p->task); //把任务插入到运行队列 insert_task_to_running(p->task, cpu0.expired); } tmp = p; p = p->next; //初始化定时器 init_task_timer(tmp); } } }}
timer.c源代码如下所示
#include "asm.h"#include "io.h"#include "idt.h"#include "video.h"#include "kernel.h"#include "8259.h"#include "timer.h"#include "task.h"void init_timer(unsigned int hz){ unsigned int divisor = CLOCK_RATE/hz; outportb(0x43, 0x36); //选择计数器0,输出模式3 outportb(0x40, divisor&0xff); //把初始值的低字节写入LSB中 outportb(0x40, (divisor>>8)&0xff); //把初始值的高字节写入MSB中}volatile unsigned long timer_ticks = 0;void do_timer(void){ timer_ticks++; //检查定时器链表 check_timer(); //管理当前任务的时间片 manage_time_slice(); outportb(M_PIC, EOI); //告诉PIC1,中断处理函数已经结束,可以处理新来的中断。 //因为定时器是连接到PIC1的IRQ0上,所以不许要通知PIC2 //调度 scheduler();}
最终的task.c源代码如下所示
#include "define.h"#include "task.h"#include "kernel.h"#include "asm.h"#include "video.h"static unsigned long task0_stack[1024] = {0};struct task_struct task0 = { //tss { //back_link 0, //esp0, ss0 (unsigned int)&(task0_stack[1023]), DATA_SEL, //esp1, ss1 0, 0, //esp2, ss2 0, 0, //cr3 0, //eip 0, //eflags 0, //eax,ecx,edx,ebx 0, 0, 0, 0, //esp,ebp 0, 0, //esi,edi 0, 0, //es,cs,ss,ds,fs,gs USER_DATA_SEL, USER_CODE_SEL, USER_DATA_SEL, USER_DATA_SEL, USER_DATA_SEL, USER_DATA_SEL, //ldt 0x20, //trace_iobitmap 0x0 }, //tss_descriptor 0, //ldt_descriptor 0, //ldt[2]; {DEFAULT_LDT_CODE, DEFAULT_LDT_DATA}, //task_function 0, //stack0 NULL, //stack3 NULL, //stack0_size 0, //stack3_size 0, //state TASK_STATE_RUNNING, //priority 0, //time_slice INITIAL_TIME_SLICE, //pid 0, //ppid 0, //next NULL, //prev NULL, //hnext NULL, //hprev NULL, //prio_array * NULL, //timer { //strcut task_struct *task NULL, //struct timer *next, *prev NULL,NULL, //int slice 0 }, //msgbox { //msg_nr 0, //msg_start 0, //msg_end 0, //box {} }};struct task_struct *current = &task0;struct run cpu0;static int newpid = 0;static int get_newpid(){ return ++newpid;}unsigned long long set_tss(unsigned long long tss_offset){ unsigned long long tss_descriptor = 0x0000890000000067ULL; tss_descriptor |= (tss_offset<<16)&0xffffff0000ULL; tss_descriptor |= (tss_offset<<32)&0xff00000000000000ULL; return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_TSS] = tss_descriptor;}unsigned long long set_ldt(unsigned long long ldt_offset){ unsigned long long ldt_descriptor = 0x000082000000000fULL; ldt_descriptor |= (ldt_offset<<16)&0xffffff0000ULL; ldt_descriptor |= (ldt_offset<<32)&0xff00000000000000ULL; return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_LDT] = ldt_descriptor;}unsigned long long get_tss(void){ return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_TSS];}unsigned long long get_ldt(void){ return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_LDT];}void init_task_timer(struct timer *timer){ if(!timer) return NULL; timer->task = NULL; //表示当前定时器非使用状态 timer->next = timer->prev = NULL; timer->time_slice = 0;}struct timer_list task_timer_list = {0, NULL, NULL};//初始化定时器链表void init_task_timer_list(){ task_timer_list.timer_nr = 0; task_timer_list.head = task_timer_list.tail = NULL;}//把定时器插入到定时器链表中//每个定时器代表一段距离,表示离左边定时器的时间片距离struct timer * add_timer(struct timer *t){ if(!t) return NULL; //当定时器链表为空时 if(task_timer_list.head == NULL) { task_timer_list.head = task_timer_list.tail = t; ++task_timer_list.timer_nr; return t; } //当定时器不为空时 struct timer *p = NULL; p = task_timer_list.head; while(p && p->time_slice <= t->time_slice) { t->time_slice -= p->time_slice; p = p->next; } if(p == task_timer_list.head) //插在最前面 { p->time_slice -= t->time_slice; p->prev = t; t->next = p; t->prev = NULL; task_timer_list.head = t; } else if(p == NULL) //插在最后面 { task_timer_list.tail->next = t; t->prev = task_timer_list.tail; t->next = NULL; task_timer_list.tail = t; } else //插在中间 { p->time_slice -= t->time_slice; p->prev->next = t; t->next = p; t->prev = p->prev; p->prev = t; } ++task_timer_list.timer_nr; return t;}//从定时器链表上移除指定任务的定时器//被sys_delete_task sys_resume_task sys_suspend_task 函数调用void remove_task_timer(struct task_struct *task){ if(!task) return ; if(!(task->timer.task)) return ; //定时器在链表中的位置有三种:表头;表尾;表中间 if(task_timer_list.head == &(task->timer)) //表头 { if(task_timer_list.tail == &(task->timer)) { task_timer_list.head = task_timer_list.tail = NULL; } else { task_timer_list.head = task->timer.next; task_timer_list.head->prev = NULL; task_timer_list.head->time_slice += task->timer.time_slice; //这条语句是必须的 } } else if(task_timer_list.tail == &(task->timer)) //表尾 { task_timer_list.tail = task->timer.prev; task_timer_list.tail->next = NULL; } else //表中间 { task->timer.prev->next = task->timer.next; task->timer.next->prev = task->timer.prev; task->timer.next->time_slice += task->timer.time_slice; //这条语句是必须的 } init_task_timer(&(task->timer));}//添加任务到任务链表尾部void add_task(struct list_pcd * list, struct task_struct *task){ if(list->head == NULL) //队列为空 { list->head = list->tail = task; task->next = task->prev = NULL; } else //队列不为空 { list->tail->next = task; task->prev = list->tail; task->next = NULL; list->tail = task; }}//从任务链表中删除任务void remove_task(struct list_pcd * list, struct task_struct *task){ //该任务在队列中有三种情况:队头;队尾;队中 if(list->head == task) //队头 { if(task->next)//队列有多个任务 { list->head = task->next; list->head->prev = NULL; } else //队列只有一个任务 { list->head = list->tail = NULL; } } else if(list->tail == task) //队尾 { if(task->prev) //队列有多个任务 { list->tail = task->prev; list->tail->next = NULL; } else //队列只有一个任务 { list->head = list->tail = NULL; } } else //队中 { task->prev->next = task->next; task->next->prev = task->prev; } }//把任务插入优先级数组中//被sys_create_task()和manage_time_slice()函数调用//本函数访问共享资源cpu0,因此要保证调用本函数时不能被打断void insert_task_to_running(struct task_struct *task, struct prio_array *py){ //都是把任务插在链表尾部 add_task(py->queue + task->priority, task); //更新任务结构 task->py = py; task->state = TASK_STATE_RUNNING; //更新优先级数组 ++(py->task_nr); py->bitmap |= (1 << task->priority);}//把任务从优先级数组上移除void remove_task_from_running(struct task_struct* task){ if(task->state != TASK_STATE_RUNNING) return; struct list_pcd *list = NULL; list = (struct list_pcd*)(task->py->queue + task->priority); //把任务从运行队列中移除 remove_task(list, task); //更新优先级数组 --(task->py->task_nr); //假如任务所在的优先级链表已空,则更新优先级位图 if(list->head == NULL) task->py->bitmap &= ~(1 << task->priority); }//初始化CPU0,把任务0插入active优先级数组中void init_cpu0(void){ struct list_pcd * list_pcd_ptr = NULL; int i = 0, j = 0; for(i = 0; i < 2; i++) { cpu0.pa[i].task_nr = 0; cpu0.pa[i].bitmap = 0x0; for(j = 0; j < PRIO_NR; j++) { cpu0.pa[i].queue[j].head = NULL; cpu0.pa[i].queue[j].tail = NULL; } } cpu0.active = cpu0.pa; cpu0.expired = cpu0.pa+1; //把任务0插入active优先级数组中去,一定要插入active优先级数组,这很重要 insert_task_to_running(&task0, cpu0.active); //把任务0插到任务HASH表中去 add_task_to_hash(&task0);}void init_tasks(void){ //设置GDT中的TSS和LDT set_tss((unsigned long long)&(task0.tss)); set_ldt((unsigned long long)&(task0.ldt)); __asm__("ltrw %%ax\n\t"::"a"(TSS_SEL)); __asm__("lldt %%ax\n\t"::"a"(LDT_SEL)); //初始化CPU0,把任务0插入expired优先级数组中 init_cpu0(); //初始化定时器链表 init_task_timer_list();}//系统调用,创建新的任务//返回新任务的PIDint sys_create_task(unsigned int task_function, unsigned int stack0_size, unsigned int stack3_size){ int pid = 0; struct task_struct *task = NULL; void *stack0 = NULL, *stack3 = NULL; stack0_size = (stack0_size ? stack0_size : DEFAULT_STACK_SIZE); stack3_size = (stack3_size ? stack3_size : DEFAULT_STACK_SIZE); task = (struct task_struct *)malloc(sizeof(struct task_struct)); stack0 = malloc(stack0_size); stack3 = malloc(stack3_size); if(!task || !stack0 || !stack3) { free(task); free(stack0); free(stack3); return -1; } *task = task0; task->tss.esp0 = stack0 + stack0_size; task->tss.eip = task_function; //task->tss.eflags = 0x3202; // I(中断位)=1,使能INTR引脚,开中断 // IOPL(i/o优先级)=3,当任务的优先级高于或等于IOPL时,I/O指令才能顺利执行。 task->tss.eflags = 0x202; //不需要设置IOPL了,通过系统调用执行I/O指令 task->tss.esp = stack3 + stack3_size; task->task_function = task_function; task->stack0 = stack0 + stack0_size; task->stack3 = stack3 + stack3_size; task->stack0_size = stack0_size; task->stack3_size = stack3_size; task->state = TASK_STATE_RUNNING; //设置时间片 task->time_slice = INITIAL_TIME_SLICE; //设置PID和PPID pid = task->pid = get_newpid(); task->ppid = current->pid; //设置优先级 task->priority = ( task->pid % PRIO_NR); //task->priority = INITIAL_PRIO; //初始化定时器 init_task_timer(&(task->timer)); //初始化任务的信箱 task->msgbox.msg_nr = 0; task->msgbox.msg_start = task->msgbox.msg_end = 0; //插入到cpu0中的expired优先级数组中 cli(); insert_task_to_running(task, cpu0.expired); //插到任务HASH表中 add_task_to_hash(task); sti(); return pid;}//计算当前任务的时间片,假如当前任务的时间片用完,则从新分配时间片,并把任务插入到expired优先级数组中//这里存在一个假设,即当前任务是所在优先级队列的第一个任务;//本函数需要访问共享资源cpu0,因此需要保证该调用该函数时不能被打断void manage_time_slice(void){ struct list_pcd * list_pcd_ptr = NULL; list_pcd_ptr = cpu0.active->queue + current->priority; //指向当前任务所在的优先级队列 //计算当前任务的时间片 if(--current->time_slice > 0) //当前任务还有时间片 { if(list_pcd_ptr->head != list_pcd_ptr->tail) //该优先级上还有>1个任务 { //轮转算法,把当前任务插到队尾 list_pcd_ptr->head = current->next; list_pcd_ptr->tail->next = current; current->prev = list_pcd_ptr->tail; list_pcd_ptr->tail = current; current->next = NULL; list_pcd_ptr->head->prev = NULL; } } else //当前任务没有时间片,从队列中摘掉该任务 { //摘取当前任务 if(list_pcd_ptr->head != list_pcd_ptr->tail) //该优先级上还有>1个任务 { list_pcd_ptr->head = current->next; list_pcd_ptr->head->prev = NULL; } else //该优先级上只有当前任务 { list_pcd_ptr->head = list_pcd_ptr->tail = NULL; //更新优先级数组位图 cpu0.active->bitmap &= ~(1 << current->priority); } //更替新优先级数组 --(cpu0.active->task_nr); //重新给任务分配时间片 current->time_slice = INITIAL_TIME_SLICE; //把任务插入expired优先级数组中 insert_task_to_running(current,cpu0.expired); }}static inline unsigned long sched_find_first_bit(const unsigned long word){ unsigned long index = word; __asm__ ("bsfl %1, %0 \n\t" \ :"=r"(index):"rm"(index)); return index;}//时间片轮转调度算法//本函数需要访问共享资源cpu0,因此需要保证该调用该函数时不能被打断,该函数必须在临界区内,不能开中断。//而且scheduler调用的函数也不能开中断void scheduler(void){ struct task_struct *v = NULL; struct list_pcd * list_pcd_ptr = NULL; struct prio_array *py = NULL; unsigned long index = 0; //加入active优先级数组中没有可运行的任务,则调换active和expired的指针。 py = cpu0.active; if(py->task_nr == 0) { cpu0.active = cpu0.expired; cpu0.expired = py; py = cpu0.active; } if(py->task_nr == 0) { sys_kprint(char_attr(BLACK,RED),"\tScheduler Error: no running task in priority array.\n"); while(1); } //在active优先级数组中找到具有任务的优先级最高的任务队列,取得任务队列的头个任务 index = sched_find_first_bit(py->bitmap); list_pcd_ptr = py->queue + index; v = list_pcd_ptr->head; if(v != current) { current->tss_descriptor = get_tss(); current->ldt_descriptor = get_ldt(); v->tss_descriptor = set_tss((unsigned long long)&(v->tss)); v->ldt_descriptor = set_ldt((unsigned long long)&(v->ldt)); current = v; __asm__ volatile("ljmp {1}quot; TSS_SEL_STR ", $0\n\t"); }}//挂起任务队列struct task_list suspend_tasks;//死亡任务队列struct task_list dead_tasks;void init_suspend_tasks(){ suspend_tasks.task_nr = 0; suspend_tasks.list.head = NULL; suspend_tasks.list.tail = NULL;}void init_dead_tasks(){ dead_tasks.task_nr = 0; dead_tasks.list.head = NULL; dead_tasks.list.tail = NULL;}//插入任务到挂起任务队列队尾void insert_task_to_suspend(struct task_struct *task){ task->state = TASK_STATE_SUSPEND; add_task(&(suspend_tasks.list), task); ++suspend_tasks.task_nr;}//插入任务到死亡任务队列队尾void insert_task_to_dead(struct task_struct *task){ task->state = TASK_STATE_DEAD; add_task(&(dead_tasks.list), task); ++dead_tasks.task_nr;}//从挂起任务队列中删除指定的任务void remove_task_from_suspend(struct task_struct *task){ if(task->state != TASK_STATE_SUSPEND) return ; remove_task(&(suspend_tasks.list), task); --suspend_tasks.task_nr;}void remove_task_from_dead(struct task_struct *task){ if(task->state != TASK_STATE_DEAD) return ; remove_task(&(dead_tasks.list), task); --dead_tasks.task_nr;}struct task_hash tasks_hash;void init_tasks_hash(){ tasks_hash.task_nr = 0; int i = 0; for(i = 0; i < TASK_HASH_NR;i++) { tasks_hash.table[i].head = tasks_hash.table[i].tail = NULL; }}void add_task_to_hash(struct task_struct *task){ struct list_pcd *list = NULL; list = &(tasks_hash.table[task->pid%TASK_HASH_NR]); if(list->head == NULL) //队列为空 { list->head = list->tail = task; task->hnext = task->hprev = NULL; } else //队列不为空 { list->tail->hnext = task; task->hprev = list->tail; task->hnext = NULL; list->tail = task; } ++tasks_hash.task_nr;}void remove_task_from_hash(struct task_struct *task){ struct list_pcd *list = NULL; list = &(tasks_hash.table[task->pid%TASK_HASH_NR]); //该任务在队列中有三种情况:队头;队尾;队中 if(list->head == task) //队头 { if(task->hnext)//队列有多个任务 { list->head = task->hnext; list->head->hprev = NULL; } else //队列只有一个任务 { list->head = list->tail = NULL; } } else if(list->tail == task) //队尾 { if(task->hprev) //队列有多个任务 { list->tail = task->hprev; list->tail->hnext = NULL; } else //队列只有一个任务 { list->head = list->tail = NULL; } } else //队中 { task->hprev->hnext = task->hnext; task->hnext->hprev = task->hprev; } --tasks_hash.task_nr; }struct task_struct * query_task_from_hash(int pid){ struct task_struct *t; t = tasks_hash.table[pid%TASK_HASH_NR].head; for(; t; t = t->hnext ) { if(t->pid == pid) return t; } return NULL;}//挂起任务//该函数访问共享资源,因此需要关中断int sys_suspend_task(int pid){ int ret = 0; struct task_struct *task = NULL; cli(); if(pid < 0) { ret = 1; goto end; } //查询是否存在这个pid的任务 task = query_task_from_hash(pid); if(!task) { ret = 2; goto end; } //判断该任务的状态,是否是RUNNING态 if(task->state != TASK_STATE_RUNNING) { ret = 3; goto end; } //把该任务从运行队列移除 remove_task_from_running(task); //把该任务添加到挂起队列 insert_task_to_suspend(task); //判断当前运行队列是否为空,假如为空则唤醒任务0 if(cpu0.active->task_nr == 0 && cpu0.expired->task_nr == 0) { //把该任务从挂起队列删除 remove_task_from_suspend(&task0); //删除任务0上的定时器 remove_task_timer(&task0); //把该任务添加到运行队列 insert_task_to_running(&task0, cpu0.expired); } //判断该PID是否是当前任务的PID if(task == current) { scheduler(); } end: sti(); return ret;}//把任务从挂起态唤醒//该函数访问共享资源,因此需要关中断int sys_resume_task(int pid){ int ret = 0; struct task_struct *task = NULL; cli(); if(pid < 0) { ret = 1; goto end; } //查询是否存在这个pid的任务 task = query_task_from_hash(pid); if(!task) { ret = 2; goto end; } //判断该任务的状态,是否是SUSPEND态 if(task->state != TASK_STATE_SUSPEND) { ret = 3; goto end; } //把该任务从挂起队列删除 remove_task_from_suspend(task); //删除任务上的定时器 remove_task_timer(task); //把该任务添加到运行队列 insert_task_to_running(task, cpu0.expired); end: sti(); return ret;}//删除任务//该函数访问共享资源,因此需要关中断int sys_delete_task(int pid){ int ret = 0; struct task_struct *task = NULL; cli(); if(pid <= 0) //不能删除任务0,因为任务0有回收死亡任务的作用 { ret = 1; goto end; } //查询是否存在这个pid的任务 task = query_task_from_hash(pid); if(!task) { ret = 2; goto end; } //判断该任务的状态 switch(task->state) { case TASK_STATE_RUNNING: //把该任务从运行队列移除 remove_task_from_running(task); break; case TASK_STATE_SUSPEND: //把该任务从挂起队列删除 remove_task_from_suspend(task); break; case TASK_STATE_DEAD: ret = 3; goto end; break; default: break; } //删除该任务上的定时器 remove_task_timer(task); //把该任务添加到死亡队列 insert_task_to_dead(task); //判断当前运行队列是否为空,假如为空则唤醒任务0 if(cpu0.active->task_nr == 0 && cpu0.expired->task_nr == 0) { //把该任务从挂起队列删除 remove_task_from_suspend(&task0); //删除任务0上的定时器 remove_task_timer(&task0); //把该任务添加到运行队列 insert_task_to_running(&task0, cpu0.expired); } //判断该PID是否是当前任务的PID if(task == current) { scheduler(); } end: sti(); return ret;}//移除死亡任务,从任务HASH表上删除,并释放任务所占的资源(比如内存)//该函数访问共享资源,因此需要关中断int sys_clear_dead_task(){ //关中断 cli(); int ret = 0; //查看死亡队列是否为空 if(dead_tasks.list.head == NULL) { ret = 1; goto end; } //遍历死亡队列 struct task_struct *p = dead_tasks.list.head; struct task_struct *tmp = NULL; while(p) { printf("clear dead task pid=%d\n", p->pid); //从hash表中移除该任务 remove_task_from_hash(p); //从死亡队列中移除该任务 remove_task_from_dead(p); //回收死亡任务所占的资源 //回收内存 free((void*)(p->stack0 - p->stack0_size)); free((void*)(p->stack3 - p->stack3_size)); tmp = p; p = p->next; free((void*)tmp); }end: //开中断 sti(); return ret;}//睡眠函数,已ms为单位 1s = 1000ms//参数ms == 0时表示该任务需要挂起,然后等待其他任务唤醒int sys_sleep(int ms){ int ret = 0; if(ms < 0) return 1; //先把睡眠时间转换为时间片 int time_slice = 0; time_slice = ms*HZ/1000; if(time_slice == 0) time_slice = 1; //初始化定时器 current->timer.task = current; current->timer.next = current->timer.prev = NULL; current->timer.time_slice = time_slice; //关中断 cli(); //把定时器插入定时器链表 add_timer(&(current->timer)); //调用sys_suspend_task函数,把自己挂起 ret = sys_suspend_task(current->pid); //开中断 sti(); return ret;}void check_timer(){ struct timer *p = NULL , *tmp = NULL; p = task_timer_list.head; //检查定时器链表 if(p) //链表上有定时器 { //定时器到点 if(--(p->time_slice) == 0) { //可能有多个定时器到点 while(p && p->time_slice == 0) { if(p->next == NULL) //只剩下一个定时器 { task_timer_list.head = task_timer_list.tail = NULL; } else //剩下多个定时器 { task_timer_list.head = p->next; task_timer_list.head->prev = NULL; } //定时器的任务为空可能是因为该任务已被删除(sys_remove_task) //定时器指定的任务有可能已经被其他任务唤醒了(使用resume_task系统调用) if(p->task && p->task->state == TASK_STATE_SUSPEND) { //从挂起队列中移除任务 remove_task_from_suspend(p->task); //把任务插入到运行队列 insert_task_to_running(p->task, cpu0.expired); } tmp = p; p = p->next; //初始化定时器 init_task_timer(tmp); } } }}int sys_send_msg(int pid, struct msg *msg){ int ret = 0; struct task_struct *task = NULL; cli(); if(pid < 0 || !msg) { ret = 1; goto end; } //查询是否存在这个pid的任务 task = query_task_from_hash(pid); if(!task) { ret = 2; goto end; } //查看任务的信箱是否有空位 if(task->msgbox.msg_nr < TASK_MSG_NR) //有空位 { //复制消息到任务的信箱的空位中 task->msgbox.msg_end = ++(task->msgbox.msg_end)%TASK_MSG_NR; task->msgbox.box[task->msgbox.msg_end] = *msg; //消息数目增1 ++(task->msgbox.msg_nr); } else //无空位 { ret = 3; goto end; }end: sti(); return ret;}int sys_receive_msg(struct msg *msg){ int ret = 0; cli(); if(!msg) { ret = 1; goto end; } //查看任务的信箱是否有消息 if(current->msgbox.msg_nr > 0) //有消息 { //复制任务信箱中的消息到msg中 current->msgbox.msg_start = ++(current->msgbox.msg_start)%TASK_MSG_NR; *msg = current->msgbox.box[current->msgbox.msg_start]; //消息数目减1 --(current->msgbox.msg_nr); } else //无消息 { ret = 2; goto end; }end: sti(); return ret;}
- 第24章 任务中定时器的设计与实现
- lua定时器与定时任务的接口设计
- 游戏定时器的设计与实现
- 定时器的实现、java定时器介绍与Spring中定时器的配置
- 定时器的实现、java定时器介绍与Spring中定时器的配置
- 定时器的实现、java定时器介绍与Spring中定时器的配置
- 定时器的实现、java定时器介绍与Spring中定时器的配置
- 定时器的实现、java定时器介绍与Spring中定时器的配置
- 定时器的实现、java定时器Timer和Quartz介绍与Spring中定时器的配置
- 定时器的实现、java定时器Timer和Quartz介绍与Spring中定时器的配置
- 定时器的实现、java定时器Timer和Quartz介绍与Spring中定时器的配置
- 定时器的实现、java定时器Timer和Quartz介绍与Spring中定时器的配置
- 定时器的实现、java定时器Timer和Quartz介绍与Spring中定时器的配置
- 定时器的实现、java定时器Timer和Quartz介绍与Spring中定时器的配置
- muduo源码分析之定时器TimerQueue的设计与实现
- linux学习笔记-定时器的设计与实现(shell)
- java定时器任务的几种实现
- 游戏中定时器的设计
- 手动创建UIWindow
- C运行时库(C Run-time Library)详解
- 第23章 扩展任务管理模块
- SQL server中A数据库往B数据库中添加表的操作
- nfs网络服务创建
- 第24章 任务中定时器的设计与实现
- 2011 下学期计划
- ANSI C
- 什么是托管C++?
- C++/CLI
- 软工第二章小结
- CLAPACK的dgeev_求特征值
- 单纯形和单纯复形
- javascript的this关键字