本文始作于2012年2月6日,刊登于人人网,于2013年2月13日迁移至此
看了好多个晚上,终于在今天把这个实验都做出来了,这个是最后结果的对比:

做完这个实验经验还是有很大长进,首先最重要的就是,实验指导书必须做为第一手知道资料,而那个《剖析》应该算作辅助,当指导书很直接要你看《剖析》上哪里哪里的时候你要好好看,如果只是提到上面哪里的内容,你应该很大概的扫视一遍,不用那么认真每行代码都看,一开始就是,指导书刚一提到fork.c程序,我就钻进去看了,每行代码都读,而且查了很多资料,还是没弄懂,最有再看指导书的时候,猛然发现跟我看的根本就没多大关系,就是有也不需要都看,所以以后还是贴着指导书看比较明智。
这个实验分为两部分,第一部分就是学会使用fork()函数进行多进程编程。这一部分需要对fork()的原理掌握得比较底层,然后就很简单了,因为sunner已经把模拟各种类型进程的函数都写出来了,你只需要学会怎么用fork()来使用他们就可以马上写完了。
第二部分是主要费时间的,大概意思是修改内核,让内核在对进程状态切换的时候输出,而且是输出到一个指定的文件/var/process.log里。创建这个文件,和打开这个文件已经告诉你了,你只需要照着做就行了。接下来的就是写一个fprintk()函数,内容也已经写好了,你只需要考虑把它放在哪,放完时候做什么,其实放在哪也已经建议你了,至于之后做什么,因为这个函数不是系统调用,只是内核里面自己用的函数,唯一要做的就是写完之后别忘了在头文件linux-0.11/include/linux/kernel.h里把这个函数的原型int fprintk(int fd, const char * fmt, ...);注册进去,以便所有内核函数在调用它的时候都能找到它。然后就是重头戏了,接下来你要把所有涉及到进程切换的函数找到,切换之处填上输出语句。这个地方做错了好多遍。
首先就是重复输出,我做好以后把文件拿出来送进stat_log.py一检查发现它报错,说我在某一行处有一个进程做了相同的事,就是之前输出过R,后来接着又输出了R,原来还不能重负阿,我想也是,状态切换就应该是不同状态之间的切换,要是相同状态之间就不存在切换了,所以又在每一句输出的时候做了些加工,就是现判断它此刻的状态是不是将要切换成的状态,如果不是才输出,这一改就得都改。
后来就进程各个状态没分清,是今天早上又看了一遍第三课的录像,然后结合《剖析》上面对那个结构体的讲解才弄明白,原来就绪跟运行用的都是TASK_RUNNING,若用state值是区分不出来的,就得想别的办法。于是我就又看了《剖析》,知道了进程队列是怎么用的。最初的想法是在全局定义一个全局变量last_state,标出现在正进行的进程的进程号,但是我无意间在代码里瞟到current这个变量,发现他就是当前整运行的进程的指针。于是就迎刃而解了。进程由就绪切换到运行用的是一个叫做switch_to()的函数,我在它上面添加这几句:
/* switch CPU */ if (current != task[next]) { fprintk(3, "%ld\t%c\t%ld\n", task[next]->pid, 'R', jiffies); if (current->state == 0) fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'J', jiffies); }
这样就没有问题了。另外,上面这个是唯一一个没有用state进行切换的,而其他的切换都是在state上直接改数值,所以你只要在老师说到的文件里用vi的/命令搜索state,然后挨个看是不是修改就都能找到了。下面是需要修改的文件的完整代码。
exit.c:
1 /* 2 * linux/kernel/exit.c 3 * 4 * (C) 1991 Linus Torvalds 5 */ 6 7 #include <errno.h> 8 #include <signal.h> 9 #include <sys/wait.h> 10 11 #include <linux/sched.h> 12 #include <linux/kernel.h> 13 #include <linux/tty.h> 14 #include <asm/segment.h> 15 16 int sys_pause(void); 17 int sys_close(int fd); 18 19 void release(struct task_struct * p) 20 { 21 int i; 22 23 if (!p) 24 return; 25 for (i=1 ; i<NR_TASKS ; i++) 26 if (task[i]==p) { 27 task[i]=NULL; 28 free_page((long)p); 29 schedule(); 30 return; 31 } 32 panic("trying to release non-existent task"); 33 } 34 35 static inline int send_sig(long sig,struct task_struct * p,int priv) 36 { 37 if (!p || sig<1 || sig>32) 38 return -EINVAL; 39 if (priv || (current->euid==p->euid) || suser()) 40 p->signal |= (1<<(sig-1)); 41 else 42 return -EPERM; 43 return 0; 44 } 45 46 static void kill_session(void) 47 { 48 struct task_struct **p = NR_TASKS + task; 49 50 while (--p > &FIRST_TASK) { 51 if (*p && (*p)->session == current->session) 52 (*p)->signal |= 1<<(SIGHUP-1); 53 } 54 } 55 56 /* 57 * XXX need to check permissions needed to send signals to process 58 * groups, etc. etc. kill() permissions semantics are tricky! 59 */ 60 int sys_kill(int pid,int sig) 61 { 62 struct task_struct **p = NR_TASKS + task; 63 int err, retval = 0; 64 65 if (!pid) while (--p > &FIRST_TASK) { 66 if (*p && (*p)->pgrp == current->pid) 67 if ((err=send_sig(sig,*p,1))) 68 retval = err; 69 } else if (pid>0) while (--p > &FIRST_TASK) { 70 if (*p && (*p)->pid == pid) 71 if ((err=send_sig(sig,*p,0))) 72 retval = err; 73 } else if (pid == -1) while (--p > &FIRST_TASK) { 74 if ((err = send_sig(sig,*p,0))) 75 retval = err; 76 } else while (--p > &FIRST_TASK) 77 if (*p && (*p)->pgrp == -pid) 78 if ((err = send_sig(sig,*p,0))) 79 retval = err; 80 return retval; 81 } 82 83 static void tell_father(int pid) 84 { 85 int i; 86 87 if (pid) 88 for (i=0;i<NR_TASKS;i++) { 89 if (!task[i]) 90 continue; 91 if (task[i]->pid != pid) 92 continue; 93 task[i]->signal |= (1<<(SIGCHLD-1)); 94 return; 95 } 96 /* if we don't find any fathers, we just release ourselves */ 97 /* This is not really OK. Must change it to make father 1 */ 98 printk("BAD BAD - no father found\n\r"); 99 release(current); 100 } 101 102 int do_exit(long code) 103 { 104 int i; 105 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); 106 free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); 107 for (i=0 ; i<NR_TASKS ; i++) 108 if (task[i] && task[i]->father == current->pid) { 109 task[i]->father = 1; 110 if (task[i]->state == TASK_ZOMBIE) 111 /* assumption task[1] is always init */ 112 (void) send_sig(SIGCHLD, task[1], 1); 113 } 114 for (i=0 ; i<NR_OPEN ; i++) 115 if (current->filp[i]) 116 sys_close(i); 117 iput(current->pwd); 118 current->pwd=NULL; 119 iput(current->root); 120 current->root=NULL; 121 iput(current->executable); 122 current->executable=NULL; 123 if (current->leader && current->tty >= 0) 124 tty_table[current->tty].pgrp = 0; 125 if (last_task_used_math == current) 126 last_task_used_math = NULL; 127 if (current->leader) 128 kill_session(); 129 current->state = TASK_ZOMBIE; 130 /* 退出 */ 131 fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'E', jiffies); 132 current->exit_code = code; 133 tell_father(current->father); 134 schedule(); 135 return (-1); /* just to suppress warnings */ 136 } 137 138 int sys_exit(int error_code) 139 { 140 return do_exit((error_code&0xff)<<8); 141 } 142 143 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) 144 { 145 int flag, code; 146 struct task_struct ** p; 147 148 verify_area(stat_addr,4); 149 repeat: 150 flag=0; 151 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { 152 if (!*p || *p == current) 153 continue; 154 if ((*p)->father != current->pid) 155 continue; 156 if (pid>0) { 157 if ((*p)->pid != pid) 158 continue; 159 } else if (!pid) { 160 if ((*p)->pgrp != current->pgrp) 161 continue; 162 } else if (pid != -1) { 163 if ((*p)->pgrp != -pid) 164 continue; 165 } 166 switch ((*p)->state) { 167 case TASK_STOPPED: 168 if (!(options & WUNTRACED)) 169 continue; 170 put_fs_long(0x7f,stat_addr); 171 return (*p)->pid; 172 case TASK_ZOMBIE: 173 current->cutime += (*p)->utime; 174 current->cstime += (*p)->stime; 175 flag = (*p)->pid; 176 code = (*p)->exit_code; 177 release(*p); 178 put_fs_long(code,stat_addr); 179 return flag; 180 default: 181 flag=1; 182 continue; 183 } 184 } 185 if (flag) { 186 if (options & WNOHANG) 187 return 0; 188 current->state=TASK_INTERRUPTIBLE; 189 /* 睡眠 */ 190 fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'W', jiffies); 191 schedule(); 192 if (!(current->signal &= ~(1<<(SIGCHLD-1)))) 193 goto repeat; 194 else 195 return -EINTR; 196 } 197 return -ECHILD; 198 }
fork.c:
1 /* 2 * linux/kernel/fork.c 3 * 4 * (C) 1991 Linus Torvalds 5 */ 6 7 /* 8 * 'fork.c' contains the help-routines for the 'fork' system call 9 * (see also system_call.s), and some misc functions ('verify_area'). 10 * Fork is rather simple, once you get the hang of it, but the memory 11 * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()' 12 */ 13 #include <errno.h> 14 15 #include <linux/sched.h> 16 #include <linux/kernel.h> 17 #include <asm/segment.h> 18 #include <asm/system.h> 19 20 extern void write_verify(unsigned long address); 21 22 long last_pid=0; 23 24 void verify_area(void * addr,int size) 25 { 26 unsigned long start; 27 28 start = (unsigned long) addr; 29 size += start & 0xfff; 30 start &= 0xfffff000; 31 start += get_base(current->ldt[2]); 32 while (size>0) { 33 size -= 4096; 34 write_verify(start); 35 start += 4096; 36 } 37 } 38 39 int copy_mem(int nr,struct task_struct * p) 40 { 41 unsigned long old_data_base,new_data_base,data_limit; 42 unsigned long old_code_base,new_code_base,code_limit; 43 44 code_limit=get_limit(0x0f); 45 data_limit=get_limit(0x17); 46 old_code_base = get_base(current->ldt[1]); 47 old_data_base = get_base(current->ldt[2]); 48 if (old_data_base != old_code_base) 49 panic("We don't support separate I&D"); 50 if (data_limit < code_limit) 51 panic("Bad data_limit"); 52 new_data_base = new_code_base = nr * 0x4000000; 53 p->start_code = new_code_base; 54 set_base(p->ldt[1],new_code_base); 55 set_base(p->ldt[2],new_data_base); 56 if (copy_page_tables(old_data_base,new_data_base,data_limit)) { 57 printk("free_page_tables: from copy_mem\n"); 58 free_page_tables(new_data_base,data_limit); 59 return -ENOMEM; 60 } 61 return 0; 62 } 63 64 /* 65 * Ok, this is the main fork-routine. It copies the system process 66 * information (task[nr]) and sets up the necessary registers. It 67 * also copies the data segment in it's entirety. 68 */ 69 int copy_process(int nr,long ebp,long edi,long esi,long gs,long none, 70 long ebx,long ecx,long edx, 71 long fs,long es,long ds, 72 long eip,long cs,long eflags,long esp,long ss) 73 { 74 struct task_struct *p; 75 int i; 76 struct file *f; 77 78 p = (struct task_struct *) get_free_page(); 79 if (!p) 80 return -EAGAIN; 81 task[nr] = p; 82 *p = *current; /* NOTE! this doesn't copy the supervisor stack */ 83 p->state = TASK_UNINTERRUPTIBLE; 84 /* new */ 85 fprintk(3, "%ld\t%c\t%ld\n", last_pid, 'N', jiffies); 86 p->pid = last_pid; 87 p->father = current->pid; 88 p->counter = p->priority; 89 p->signal = 0; 90 p->alarm = 0; 91 p->leader = 0; /* process leadership doesn't inherit */ 92 p->utime = p->stime = 0; 93 p->cutime = p->cstime = 0; 94 p->start_time = jiffies; 95 p->tss.back_link = 0; 96 p->tss.esp0 = PAGE_SIZE + (long) p; 97 p->tss.ss0 = 0x10; 98 p->tss.eip = eip; 99 p->tss.eflags = eflags; 100 p->tss.eax = 0; 101 p->tss.ecx = ecx; 102 p->tss.edx = edx; 103 p->tss.ebx = ebx; 104 p->tss.esp = esp; 105 p->tss.ebp = ebp; 106 p->tss.esi = esi; 107 p->tss.edi = edi; 108 p->tss.es = es & 0xffff; 109 p->tss.cs = cs & 0xffff; 110 p->tss.ss = ss & 0xffff; 111 p->tss.ds = ds & 0xffff; 112 p->tss.fs = fs & 0xffff; 113 p->tss.gs = gs & 0xffff; 114 p->tss.ldt = _LDT(nr); 115 p->tss.trace_bitmap = 0x80000000; 116 if (last_task_used_math == current) 117 __asm__("clts ; fnsave %0"::"m" (p->tss.i387)); 118 if (copy_mem(nr,p)) { 119 task[nr] = NULL; 120 free_page((long) p); 121 return -EAGAIN; 122 } 123 for (i=0; i<NR_OPEN;i++) 124 if ((f=p->filp[i])) 125 f->f_count++; 126 if (current->pwd) 127 current->pwd->i_count++; 128 if (current->root) 129 current->root->i_count++; 130 if (current->executable) 131 current->executable->i_count++; 132 set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); 133 set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); 134 p->state = TASK_RUNNING; /* do this last, just in case */ 135 /* ready */ 136 fprintk(3, "%ld\t%c\t%ld\n", p->pid, 'J', jiffies); 137 return last_pid; 138 } 139 140 int find_empty_process(void) 141 { 142 int i; 143 144 repeat: 145 if ((++last_pid)<0) last_pid=1; 146 for(i=0 ; i<NR_TASKS ; i++) 147 if (task[i] && task[i]->pid == last_pid) goto repeat; 148 for(i=1 ; i<NR_TASKS ; i++) 149 if (!task[i]) 150 return i; 151 return -EAGAIN; 152 }
schde.c:
1 /* 2 * linux/kernel/sched.c 3 * 4 * (C) 1991 Linus Torvalds 5 */ 6 7 /* 8 * 'sched.c' is the main kernel file. It contains scheduling primitives 9 * (sleep_on, wakeup, schedule etc) as well as a number of simple system 10 * call functions (type getpid(), which just extracts a field from 11 * current-task 12 */ 13 #include <linux/sched.h> 14 #include <linux/kernel.h> 15 #include <linux/sys.h> 16 #include <linux/fdreg.h> 17 #include <asm/system.h> 18 #include <asm/io.h> 19 #include <asm/segment.h> 20 21 #include <signal.h> 22 23 #define _S(nr) (1<<((nr)-1)) 24 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) 25 26 void show_task(int nr,struct task_struct * p) 27 { 28 int i,j = 4096-sizeof(struct task_struct); 29 30 printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state); 31 i=0; 32 while (i<j && !((char *)(p+1))[i]) 33 i++; 34 printk("%d (of %d) chars free in kernel stack\n\r",i,j); 35 } 36 37 void show_stat(void) 38 { 39 int i; 40 41 for (i=0;i<NR_TASKS;i++) 42 if (task[i]) 43 show_task(i,task[i]); 44 } 45 46 #define LATCH (1193180/HZ) 47 48 extern void mem_use(void); 49 50 extern int timer_interrupt(void); 51 extern int system_call(void); 52 53 union task_union { 54 struct task_struct task; 55 char stack[PAGE_SIZE]; 56 }; 57 58 static union task_union init_task = {INIT_TASK,}; 59 60 long volatile jiffies=0; 61 long startup_time=0; 62 struct task_struct *current = &(init_task.task); 63 struct task_struct *last_task_used_math = NULL; 64 65 struct task_struct * task[NR_TASKS] = {&(init_task.task), }; 66 67 long user_stack [ PAGE_SIZE>>2 ] ; 68 69 struct { 70 long * a; 71 short b; 72 } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 }; 73 /* 74 * 'math_state_restore()' saves the current math information in the 75 * old math state array, and gets the new ones from the current task 76 */ 77 void math_state_restore() 78 { 79 if (last_task_used_math == current) 80 return; 81 __asm__("fwait"); 82 if (last_task_used_math) { 83 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387)); 84 } 85 last_task_used_math=current; 86 if (current->used_math) { 87 __asm__("frstor %0"::"m" (current->tss.i387)); 88 } else { 89 __asm__("fninit"::); 90 current->used_math=1; 91 } 92 } 93 94 /* 95 * 'schedule()' is the scheduler function. This is GOOD CODE! There 96 * probably won't be any reason to change this, as it should work well 97 * in all circumstances (ie gives IO-bound processes good response etc). 98 * The one thing you might take a look at is the signal-handler code here. 99 * 100 * NOTE!! Task 0 is the 'idle' task, which gets called when no other 101 * tasks can run. It can not be killed, and it cannot sleep. The 'state' 102 * information in task[0] is never used. 103 */ 104 void schedule(void) 105 { 106 int i,next,c; 107 struct task_struct ** p; 108 109 /* check alarm, wake up any interruptible tasks that have got a signal */ 110 111 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) 112 if (*p) { 113 if ((*p)->alarm && (*p)->alarm < jiffies) { 114 (*p)->signal |= (1<<(SIGALRM-1)); 115 (*p)->alarm = 0; 116 } 117 if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) && 118 (*p)->state==TASK_INTERRUPTIBLE) { 119 /* running */ 120 if ((*p)->state != TASK_RUNNING) 121 fprintk(3, "%ld\t%c\t%ld\n", (*p)->pid, 'J', jiffies); 122 (*p)->state=TASK_RUNNING; 123 } 124 } 125 126 /* this is the scheduler proper: */ 127 128 while (1) { 129 c = -1; 130 next = 0; 131 i = NR_TASKS; 132 p = &task[NR_TASKS]; 133 while (--i) { 134 if (!*--p) 135 continue; 136 if ((*p)->state == TASK_RUNNING && (*p)->counter > c) 137 c = (*p)->counter, next = i; 138 } 139 if (c) break; 140 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) 141 if (*p) 142 (*p)->counter = ((*p)->counter >> 1) + 143 (*p)->priority; 144 } 145 /* switch CPU */ 146 if (current != task[next]) { 147 fprintk(3, "%ld\t%c\t%ld\n", task[next]->pid, 'R', jiffies); 148 if (current->state == 0) 149 fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'J', jiffies); 150 } 151 switch_to(next); 152 } 153 154 int sys_pause(void) 155 { 156 /* wait */ 157 if (current->state != TASK_INTERRUPTIBLE) 158 fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'W', jiffies); 159 current->state = TASK_INTERRUPTIBLE; 160 schedule(); 161 return 0; 162 } 163 164 void sleep_on(struct task_struct **p) 165 { 166 struct task_struct *tmp; 167 168 if (!p) 169 return; 170 if (current == &(init_task.task)) 171 panic("task[0] trying to sleep"); 172 tmp = *p; 173 *p = current; 174 /* wait */ 175 if (current->state != TASK_UNINTERRUPTIBLE) 176 fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'W', jiffies); 177 current->state = TASK_UNINTERRUPTIBLE; 178 schedule(); 179 if (tmp) { 180 /* running */ 181 if (tmp->state != 0) 182 fprintk(3, "%ld\t%c\t%ld\n", tmp->pid, 'J', jiffies); 183 tmp->state=0; 184 } 185 } 186 187 void interruptible_sleep_on(struct task_struct **p) 188 { 189 struct task_struct *tmp; 190 191 if (!p) 192 return; 193 if (current == &(init_task.task)) 194 panic("task[0] trying to sleep"); 195 tmp=*p; 196 *p=current; 197 repeat: 198 /* wait */ 199 if (current->state != TASK_INTERRUPTIBLE) 200 fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'W', jiffies); 201 current->state = TASK_INTERRUPTIBLE; 202 schedule(); 203 if (*p && *p != current) { 204 /* running */ 205 if ((**p).state != 0) 206 fprintk(3, "%ld\t%c\t%ld\n", (**p).pid, 'J', jiffies); 207 (**p).state=0; 208 goto repeat; 209 } 210 *p=NULL; 211 if (tmp) { 212 /* running */ 213 if (tmp->state != 0) 214 fprintk(3, "%ld\t%c\t%ld\n", tmp->pid, 'J', jiffies); 215 tmp->state=0; 216 } 217 } 218 219 void wake_up(struct task_struct **p) 220 { 221 if (p && *p) { 222 /* running */ 223 if ((**p).state != 0) 224 fprintk(3, "%ld\t%c\t%ld\n", (**p).pid, 'J', jiffies); 225 (**p).state=0; 226 *p=NULL; 227 } 228 } 229 230 /* 231 * OK, here are some floppy things that shouldn't be in the kernel 232 * proper. They are here because the floppy needs a timer, and this 233 * was the easiest way of doing it. 234 */ 235 static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL}; 236 static int mon_timer[4]={0,0,0,0}; 237 static int moff_timer[4]={0,0,0,0}; 238 unsigned char current_DOR = 0x0C; 239 240 int ticks_to_floppy_on(unsigned int nr) 241 { 242 extern unsigned char selected; 243 unsigned char mask = 0x10 << nr; 244 245 if (nr>3) 246 panic("floppy_on: nr>3"); 247 moff_timer[nr]=10000; /* 100 s = very big :-) */ 248 cli(); /* use floppy_off to turn it off */ 249 mask |= current_DOR; 250 if (!selected) { 251 mask &= 0xFC; 252 mask |= nr; 253 } 254 if (mask != current_DOR) { 255 outb(mask,FD_DOR); 256 if ((mask ^ current_DOR) & 0xf0) 257 mon_timer[nr] = HZ/2; 258 else if (mon_timer[nr] < 2) 259 mon_timer[nr] = 2; 260 current_DOR = mask; 261 } 262 sti(); 263 return mon_timer[nr]; 264 } 265 266 void floppy_on(unsigned int nr) 267 { 268 cli(); 269 while (ticks_to_floppy_on(nr)) 270 sleep_on(nr+wait_motor); 271 sti(); 272 } 273 274 void floppy_off(unsigned int nr) 275 { 276 moff_timer[nr]=3*HZ; 277 } 278 279 void do_floppy_timer(void) 280 { 281 int i; 282 unsigned char mask = 0x10; 283 284 for (i=0 ; i<4 ; i++,mask <<= 1) { 285 if (!(mask & current_DOR)) 286 continue; 287 if (mon_timer[i]) { 288 if (!--mon_timer[i]) 289 wake_up(i+wait_motor); 290 } else if (!moff_timer[i]) { 291 current_DOR &= ~mask; 292 outb(current_DOR,FD_DOR); 293 } else 294 moff_timer[i]--; 295 } 296 } 297 298 #define TIME_REQUESTS 64 299 300 static struct timer_list { 301 long jiffies; 302 void (*fn)(); 303 struct timer_list * next; 304 } timer_list[TIME_REQUESTS], * next_timer = NULL; 305 306 void add_timer(long jiffies, void (*fn)(void)) 307 { 308 struct timer_list * p; 309 310 if (!fn) 311 return; 312 cli(); 313 if (jiffies <= 0) 314 (fn)(); 315 else { 316 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++) 317 if (!p->fn) 318 break; 319 if (p >= timer_list + TIME_REQUESTS) 320 panic("No more time requests free"); 321 p->fn = fn; 322 p->jiffies = jiffies; 323 p->next = next_timer; 324 next_timer = p; 325 while (p->next && p->next->jiffies < p->jiffies) { 326 p->jiffies -= p->next->jiffies; 327 fn = p->fn; 328 p->fn = p->next->fn; 329 p->next->fn = fn; 330 jiffies = p->jiffies; 331 p->jiffies = p->next->jiffies; 332 p->next->jiffies = jiffies; 333 p = p->next; 334 } 335 } 336 sti(); 337 } 338 339 void do_timer(long cpl) 340 { 341 extern int beepcount; 342 extern void sysbeepstop(void); 343 344 if (beepcount) 345 if (!--beepcount) 346 sysbeepstop(); 347 348 if (cpl) 349 current->utime++; 350 else 351 current->stime++; 352 353 if (next_timer) { 354 next_timer->jiffies--; 355 while (next_timer && next_timer->jiffies <= 0) { 356 void (*fn)(void); 357 358 fn = next_timer->fn; 359 next_timer->fn = NULL; 360 next_timer = next_timer->next; 361 (fn)(); 362 } 363 } 364 if (current_DOR & 0xf0) 365 do_floppy_timer(); 366 if ((--current->counter)>0) return; 367 current->counter=0; 368 if (!cpl) return; 369 schedule(); 370 } 371 372 int sys_alarm(long seconds) 373 { 374 int old = current->alarm; 375 376 if (old) 377 old = (old - jiffies) / HZ; 378 current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; 379 return (old); 380 } 381 382 int sys_getpid(void) 383 { 384 return current->pid; 385 } 386 387 int sys_getppid(void) 388 { 389 return current->father; 390 } 391 392 int sys_getuid(void) 393 { 394 return current->uid; 395 } 396 397 int sys_geteuid(void) 398 { 399 return current->euid; 400 } 401 402 int sys_getgid(void) 403 { 404 return current->gid; 405 } 406 407 int sys_getegid(void) 408 { 409 return current->egid; 410 } 411 412 int sys_nice(long increment) 413 { 414 if (current->priority-increment>0) 415 current->priority -= increment; 416 return 0; 417 } 418 419 void sched_init(void) 420 { 421 int i; 422 struct desc_struct * p; 423 424 if (sizeof(struct sigaction) != 16) 425 panic("Struct sigaction MUST be 16 bytes"); 426 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); 427 set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); 428 p = gdt+2+FIRST_TSS_ENTRY; 429 for(i=1;i<NR_TASKS;i++) { 430 task[i] = NULL; 431 p->a=p->b=0; 432 p++; 433 p->a=p->b=0; 434 p++; 435 } 436 /* Clear NT, so that we won't have troubles with that later on */ 437 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); 438 ltr(0); 439 lldt(0); 440 outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ 441 outb_p(LATCH & 0xff , 0x40); /* LSB */ 442 outb(LATCH >> 8 , 0x40); /* MSB */ 443 set_intr_gate(0x20,&timer_interrupt); 444 outb(inb_p(0x21)&~0x01,0x21); 445 set_system_gate(0x80,&system_call); 446 }
浙公网安备 33010602011771号