?? sched.c
字號(hào):
unsigned char mask = 0x10 << nr; // 所選軟驅(qū)對(duì)應(yīng)數(shù)字輸出寄存器中啟動(dòng)馬達(dá)比特位。 if (nr > 3) panic ("floppy_on: nr>3"); // 最多4 個(gè)軟驅(qū)。 moff_timer[nr] = 10000; /* 100 s = very big :-) */ cli (); /* use floppy_off to turn it off */ mask |= current_DOR;// 如果不是當(dāng)前軟驅(qū),則首先復(fù)位其它軟驅(qū)的選擇位,然后置對(duì)應(yīng)軟驅(qū)選擇位。 if (!selected) { mask &= 0xFC; mask |= nr; }// 如果數(shù)字輸出寄存器的當(dāng)前值與要求的值不同,則向FDC 數(shù)字輸出端口輸出新值(mask)。并且如果// 要求啟動(dòng)的馬達(dá)還沒(méi)有啟動(dòng),則置相應(yīng)軟驅(qū)的馬達(dá)啟動(dòng)定時(shí)器值(HZ/2 = 0.5 秒或50 個(gè)滴答)。// 此后更新當(dāng)前數(shù)字輸出寄存器值current_DOR。 if (mask != current_DOR) { outb (mask, FD_DOR); if ((mask ^ current_DOR) & 0xf0) mon_timer[nr] = HZ / 2; else if (mon_timer[nr] < 2) mon_timer[nr] = 2; current_DOR = mask; } sti (); return mon_timer[nr];}// 等待指定軟驅(qū)馬達(dá)啟動(dòng)所需時(shí)間。void floppy_on (unsigned int nr){ cli (); // 關(guān)中斷。 while (ticks_to_floppy_on (nr)) // 如果馬達(dá)啟動(dòng)定時(shí)還沒(méi)到,就一直把當(dāng)前進(jìn)程置 sleep_on (nr + wait_motor); // 為不可中斷睡眠狀態(tài)并放入等待馬達(dá)運(yùn)行的隊(duì)列中。 sti (); // 開(kāi)中斷。}// 置關(guān)閉相應(yīng)軟驅(qū)馬達(dá)停轉(zhuǎn)定時(shí)器(3 秒)。void floppy_off (unsigned int nr){ moff_timer[nr] = 3 * HZ;}// 軟盤定時(shí)處理子程序。更新馬達(dá)啟動(dòng)定時(shí)值和馬達(dá)關(guān)閉停轉(zhuǎn)計(jì)時(shí)值。該子程序是在時(shí)鐘定時(shí)// 中斷中被調(diào)用,因此每一個(gè)滴答(10ms)被調(diào)用一次,更新馬達(dá)開(kāi)啟或停轉(zhuǎn)定時(shí)器的值。如果某// 一個(gè)馬達(dá)停轉(zhuǎn)定時(shí)到,則將數(shù)字輸出寄存器馬達(dá)啟動(dòng)位復(fù)位。void do_floppy_timer (void){ int i; unsigned char mask = 0x10; for (i = 0; i < 4; i++, mask <<= 1) { if (!(mask & current_DOR)) // 如果不是DOR 指定的馬達(dá)則跳過(guò)。 continue; if (mon_timer[i]) { if (!--mon_timer[i]) wake_up (i + wait_motor); // 如果馬達(dá)啟動(dòng)定時(shí)到則喚醒進(jìn)程。 } else if (!moff_timer[i]) { // 如果馬達(dá)停轉(zhuǎn)定時(shí)到則 current_DOR &= ~mask; // 復(fù)位相應(yīng)馬達(dá)啟動(dòng)位,并 outb (current_DOR, FD_DOR); // 更新數(shù)字輸出寄存器。 } else moff_timer[i]--; // 馬達(dá)停轉(zhuǎn)計(jì)時(shí)遞減。 }}#define TIME_REQUESTS 64 // 最多可有64 個(gè)定時(shí)器鏈表(64 個(gè)任務(wù))。// 定時(shí)器鏈表結(jié)構(gòu)和定時(shí)器數(shù)組。static struct timer_list{ long jiffies; // 定時(shí)滴答數(shù)。 void (*fn) (); // 定時(shí)處理程序。 struct timer_list *next; // 下一個(gè)定時(shí)器。}timer_list[TIME_REQUESTS], *next_timer = NULL;// 添加定時(shí)器。輸入?yún)?shù)為指定的定時(shí)值(滴答數(shù))和相應(yīng)的處理程序指針。// jiffies – 以10 毫秒計(jì)的滴答數(shù);*fn()- 定時(shí)時(shí)間到時(shí)執(zhí)行的函數(shù)。void add_timer (long jiffies, void (*fn) ()){ struct timer_list *p; // 如果定時(shí)處理程序指針為空,則退出。 if (!fn) return; cli (); // 如果定時(shí)值<=0,則立刻調(diào)用其處理程序。并且該定時(shí)器不加入鏈表中。 if (jiffies <= 0) (fn) (); else { // 從定時(shí)器數(shù)組中,找一個(gè)空閑項(xiàng)。 for (p = timer_list; p < timer_list + TIME_REQUESTS; p++) if (!p->fn) break; // 如果已經(jīng)用完了定時(shí)器數(shù)組,則系統(tǒng)崩潰?。 if (p >= timer_list + TIME_REQUESTS) panic ("No more time requests free"); // 向定時(shí)器數(shù)據(jù)結(jié)構(gòu)填入相應(yīng)信息。并鏈入鏈表頭 p->fn = fn; p->jiffies = jiffies; p->next = next_timer; next_timer = p;// 鏈表項(xiàng)按定時(shí)值從小到大排序。在排序時(shí)減去排在前面需要的滴答數(shù),這樣在處理定時(shí)器時(shí)只要// 查看鏈表頭的第一項(xiàng)的定時(shí)是否到期即可。[[?? 這段程序好象沒(méi)有考慮周全。如果新插入的定時(shí)// 器值 < 原來(lái)頭一個(gè)定時(shí)器值時(shí),也應(yīng)該將所有后面的定時(shí)值均減去新的第1 個(gè)的定時(shí)值。]] while (p->next && p->next->jiffies < p->jiffies) { p->jiffies -= p->next->jiffies; fn = p->fn; p->fn = p->next->fn; p->next->fn = fn; jiffies = p->jiffies; p->jiffies = p->next->jiffies; p->next->jiffies = jiffies; p = p->next; } } sti ();}//// 時(shí)鐘中斷C 函數(shù)處理程序,在kernel/system_call.s 中的_timer_interrupt(176 行)被調(diào)用。// 參數(shù)cpl 是當(dāng)前特權(quán)級(jí)0 或3,0 表示內(nèi)核代碼在執(zhí)行。// 對(duì)于一個(gè)進(jìn)程由于執(zhí)行時(shí)間片用完時(shí),則進(jìn)行任務(wù)切換。并執(zhí)行一個(gè)計(jì)時(shí)更新工作。void do_timer (long cpl){ extern int beepcount; // 揚(yáng)聲器發(fā)聲時(shí)間滴答數(shù)(kernel/chr_drv/console.c,697) extern void sysbeepstop (void); // 關(guān)閉揚(yáng)聲器(kernel/chr_drv/console.c,691) // 如果發(fā)聲計(jì)數(shù)次數(shù)到,則關(guān)閉發(fā)聲。(向0x61 口發(fā)送命令,復(fù)位位0 和1。位0 控制8253 // 計(jì)數(shù)器2 的工作,位1 控制揚(yáng)聲器)。 if (beepcount) if (!--beepcount) sysbeepstop (); // 如果當(dāng)前特權(quán)級(jí)(cpl)為0(最高,表示是內(nèi)核程序在工作),則將超級(jí)用戶運(yùn)行時(shí)間stime 遞增; // 如果cpl > 0,則表示是一般用戶程序在工作,增加utime。 if (cpl) current->utime++; else current->stime++;// 如果有用戶的定時(shí)器存在,則將鏈表第1 個(gè)定時(shí)器的值減1。如果已等于0,則調(diào)用相應(yīng)的處理// 程序,并將該處理程序指針置為空。然后去掉該項(xiàng)定時(shí)器。 if (next_timer) { // next_timer 是定時(shí)器鏈表的頭指針(見(jiàn)270 行)。 next_timer->jiffies--; while (next_timer && next_timer->jiffies <= 0) { void (*fn) (); // 這里插入了一個(gè)函數(shù)指針定義!!!?? fn = next_timer->fn; next_timer->fn = NULL; next_timer = next_timer->next; (fn) (); // 調(diào)用處理函數(shù)。 } }// 如果當(dāng)前軟盤控制器FDC 的數(shù)字輸出寄存器中馬達(dá)啟動(dòng)位有置位的,則執(zhí)行軟盤定時(shí)程序(245 行)。 if (current_DOR & 0xf0) do_floppy_timer (); if ((--current->counter) > 0) return; // 如果進(jìn)程運(yùn)行時(shí)間還沒(méi)完,則退出。 current->counter = 0; if (!cpl) return; // 對(duì)于超級(jí)用戶程序,不依賴counter 值進(jìn)行調(diào)度。 schedule ();}// 系統(tǒng)調(diào)用功能 - 設(shè)置報(bào)警定時(shí)時(shí)間值(秒)。// 如果已經(jīng)設(shè)置過(guò)alarm 值,則返回舊值,否則返回0。int sys_alarm (long seconds){ int old = current->alarm; if (old) old = (old - jiffies) / HZ; current->alarm = (seconds > 0) ? (jiffies + HZ * seconds) : 0; return (old);}// 取當(dāng)前進(jìn)程號(hào)pid。int sys_getpid (void){ return current->pid;}// 取父進(jìn)程號(hào)ppid。int sys_getppid (void){ return current->father;}// 取用戶號(hào)uid。int sys_getuid (void){ return current->uid;}// 取euid。int sys_geteuid (void){ return current->euid;}// 取組號(hào)gid。int sys_getgid (void){ return current->gid;}// 取egid。int sys_getegid (void){ return current->egid;}// 系統(tǒng)調(diào)用功能 -- 降低對(duì)CPU 的使用優(yōu)先權(quán)(有人會(huì)用嗎??)。// 應(yīng)該限制increment 大于0,否則的話,可使優(yōu)先權(quán)增大!!int sys_nice (long increment){ if (current->priority - increment > 0) current->priority -= increment; return 0;}// 調(diào)度程序的初始化子程序。void sched_init (void){ int i; struct desc_struct *p; // 描述符表結(jié)構(gòu)指針。 if (sizeof (struct sigaction) != 16) // sigaction 是存放有關(guān)信號(hào)狀態(tài)的結(jié)構(gòu)。 panic ("Struct sigaction MUST be 16 bytes");// 設(shè)置初始任務(wù)(任務(wù)0)的任務(wù)狀態(tài)段描述符和局部數(shù)據(jù)表描述符(include/asm/system.h,65)。 set_tss_desc (gdt + FIRST_TSS_ENTRY, &(init_task.task.tss)); set_ldt_desc (gdt + FIRST_LDT_ENTRY, &(init_task.task.ldt));// 清任務(wù)數(shù)組和描述符表項(xiàng)(注意i=1 開(kāi)始,所以初始任務(wù)的描述符還在)。 p = gdt + 2 + FIRST_TSS_ENTRY; for (i = 1; i < NR_TASKS; i++) { task[i] = NULL; p->a = p->b = 0; p++; p->a = p->b = 0; p++; }/* 清除標(biāo)志寄存器中的位NT,這樣以后就不會(huì)有麻煩 */// NT 標(biāo)志用于控制程序的遞歸調(diào)用(Nested Task)。當(dāng)NT 置位時(shí),那么當(dāng)前中斷任務(wù)執(zhí)行// iret 指令時(shí)就會(huì)引起任務(wù)切換。NT 指出TSS 中的back_link 字段是否有效。// __asm__ ("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); // 復(fù)位NT 標(biāo)志。
_asm pushfd; _asm and dword ptr ss:[esp],0xffffbfff; _asm popfd; ltr (0); // 將任務(wù)0 的TSS 加載到任務(wù)寄存器tr。 lldt (0); // 將局部描述符表加載到局部描述符表寄存器。// 注意!!是將GDT 中相應(yīng)LDT 描述符的選擇符加載到ldtr。只明確加載這一次,以后新任務(wù)// LDT 的加載,是CPU 根據(jù)TSS 中的LDT 項(xiàng)自動(dòng)加載。// 下面代碼用于初始化8253 定時(shí)器。 outb_p (0x36, 0x43); /* binary, mode 3, LSB/MSB, ch 0 */ outb_p (LATCH & 0xff, 0x40); /* LSB */// 定時(shí)值低字節(jié)。 outb (LATCH >> 8, 0x40); /* MSB */// 定時(shí)值高字節(jié)。 // 設(shè)置時(shí)鐘中斷處理程序句柄(設(shè)置時(shí)鐘中斷門)。 set_intr_gate (0x20, &timer_interrupt); // 修改中斷控制器屏蔽碼,允許時(shí)鐘中斷。 outb (inb_p (0x21) & ~0x01, 0x21); // 設(shè)置系統(tǒng)調(diào)用中斷門。 set_system_gate (0x80, &system_call);}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -