我今晚有一个操作系统项目要交,需要澄清一个话题。我们使用的是XINU操作系统。我正在尝试更改默认的操作系统调度程序,以解决某些进程正处于饥饿状态的问题。我被定向到clkint.S文件,我认为它就是时钟中断处理程序。我的问题是,我如何知道它被中断的频率?我如何设置时间,比方说每5秒调用一次函数?我看过英特尔的x86手册,但他们有大量的信息要筛选,我没有时间,如果有人能给我指出正确的方向,我将不胜感激。
下面是我认为有必要的几个文件:
clkint.S:
/* clkint.s - _clkint */
#include <icu.s>
.text
count1000: .word 1000
.globl sltop
.globl clkint
clkint:
pushal
cli
movb $EOI,%al
outb %al,$OCW1_2
incl ctr1000
subw $1,count1000
ja cl1
incl clktime
movw $1000,count1000
cl1:
cmpl $0,slnonempty # if no sleeping processes,
je clpreem # skip to preemption check
movl sltop,%eax # decrement key of first
decl (%eax) # sleeping process
jg clpreem # must use jg for signed int
call wakeup # if zero, call wakeup
clpreem: decl preempt # decrement preemption counter
jg clret # must use jg for signed int
call resched # if preemption, call resched
clret: # return from interrupt
sti
popal
iretclkinit.c:
/* clkinit.c - clkinit */
#include <xinu.h>
#include <interrupt.h>
#include <clock.h>
uint32 clktime; /* seconds since boot */
uint32 ctr1000 = 0; /* milliseconds since boot */
qid16 sleepq; /* queue of sleeping processes */
int32 slnempty; /* zero if the sleep queue is empty; */
/* non-zero otherwise */
int32 *sltop; /* ptr to key in first entry of sleepq */
/* if sleepq is not empty */
uint32 preempt; /* preemption counter */
/*------------------------------------------------------------------------
* clkinit - initialize the clock and sleep queue at startup
*------------------------------------------------------------------------
*/
void clkinit(void)
{
uint16 intv; /* clock rate in KHz */
/* Set interrupt vector for clock to invoke clkint */
set_evec(IRQBASE, (uint32)clkint);
/* clock rate is 1.190 Mhz; this is 10ms interrupt rate */
intv = 1190;
sleepq = newqueue(); /* allocate a queue to hold the delta */
/* list of sleeping processes */
preempt = QUANTUM; /* initial time quantum */
/* Specify that seepq is initially empty */
slnonempty = FALSE;
clktime = 0; /* start counting seconds */
/* set to: timer 0, 16-bit counter, rate generator mode,
counter is binary */
outb(CLKCNTL, 0x34);
/* must write LSB first, then MSB */
outb(CLOCK0, (char)intv);
outb(CLOCK0, intv>>8);
return;
}clkhandler.c:
/* clkhandler.c - clkhandler */
#include <xinu.h>
/*------------------------------------------------------------------------
* clkhandler - handle clock interrupt and process preemption events
* as well as awakening sleeping processes
*------------------------------------------------------------------------
*/
interrupt clkhandler(void)
{
clkupdate(CLKCYCS_PER_TICK);
/* record clock ticks */
clkticks++;
/* update global counter for seconds */
if (clkticks == CLKTICKS_PER_SEC) {
clktime++;
clkticks = 0;
}
/* If sleep queue is nonempty, decrement first key; when the */
/* key reaches zero, awaken a sleeping process */
if (nonempty(sleepq) && (--firstkey(sleepq) <= 0)) {
wakeup();
}
/* Check to see if this proc should be preempted */
if (--preempt <= 0) {
preempt = QUANTUM;
resched();
}
return;
}我可以自己添加所有的饥饿功能,我只需要弄清楚如何让clkin.s处理程序每隔5秒调用我的函数一次……我不明白时钟是如何工作的,也不知道整个程序集是如何工作的。我不是要求别人给我一个解决方案,我只是需要一些指导。
发布于 2013-03-20 06:15:40
intv是用于调度(至少在此代码中)的中断计时器的时间切片粒度(单位: Khz)。每隔5秒听起来非常慢,可能会使您的系统几乎没有响应,尝试毫秒的数量级。
要计算一个新的间隔,您需要更改此值并对频率进行一些计算。你也许可以通过在intv上完成的计算得出这一步,得到10ms。
在x86中,可通过使用outb汇编指令将KHz中的定时器中断值写入端口0x40来建立定时器值。如代码所示,您必须先写入最低有效字节,然后写入最高有效字节(outb一次写入一个字节)。要启用计时器,您可以向同一端口写入0x36,并且必须将IRQ处理程序绑定到IRQ0以接收中断。我试着为你压缩了一点信息,但这是x86特有的。
https://stackoverflow.com/questions/15511507
复制相似问题