Assembly 修改时钟中断处理程序xinu

Assembly 修改时钟中断处理程序xinu,assembly,operating-system,x86,interrupt,Assembly,Operating System,X86,Interrupt,今晚我有一个操作系统项目,需要澄清一个主题。我们正在使用操作系统XINU。我正在尝试更改默认的OS调度程序,以考虑某些进程的不足。我被引导到clkint.S文件,我认为它是时钟中断处理程序。我的问题是,我如何知道它多久中断一次?我如何设置每5秒进行一次函数调用的时间?我看过英特尔x86手册,但它们有大量的信息需要筛选,我的时间很短。如果有人能给我指出正确的方向,我将不胜感激 以下是我认为必要的几个文件: clkint.S: /* clkint.s - _clkint */ #incl

今晚我有一个操作系统项目,需要澄清一个主题。我们正在使用操作系统XINU。我正在尝试更改默认的OS调度程序,以考虑某些进程的不足。我被引导到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
        iret
clkint.S:
/*clkint.s-\u clkint*/
#包括
.文本
count1000:。单词1000
.globl sltop
格洛比尔·克金特先生
clkint:
普沙尔
cli
movb$EOI,%al
支出%al,$OCW1_2
包括ctr1000
subw$1000
ja cl1
包括clktime
movw$1000,count1000
cl1:
cmpl$0,slnonempty#如果没有睡眠进程,
je CLPREEME#跳到抢占检查
movl sltop,%eax#第一个的减量键
decl(%eax)#睡眠过程
jg clpreem#必须将jg用于签名整数
呼叫唤醒#如果为零,则呼叫唤醒
CLPREEME:decl抢占#减量抢占计数器
jg clret#必须将jg用于有符号整数
调用resched#如果抢占,则调用resched
clret:#从中断返回
性病
波帕尔
艾雷特
clkinit.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;
}
/*clkinit.c-clkinit*/
#包括
#包括
#包括
uint32 clktime;/*开机后的秒数*/
uint32 ctr1000=0;/*启动后的毫秒数*/
qid16 sleepq;/*休眠进程队列*/
int32 slnempty;/*如果睡眠队列为空,则为零*/
/*否则为非零*/
int32*sltop;/*ptr输入sleepq的第一个条目*/
/*如果sleepq不是空的*/
uint32抢占;/*抢占计数器*/
/*------------------------------------------------------------------------
*clkinit-启动时初始化时钟和睡眠队列
*------------------------------------------------------------------------
*/
作废clkinit(作废)
{
uint16 intv;/*时钟频率,单位为KHz*/
/*为调用clkint的时钟设置中断向量*/
设定值(IRQBASE,(uint32)clkint);
/*时钟频率为1.190 Mhz;这是10毫秒的中断频率*/
intv=1190;
sleepq=newqueue();/*分配一个队列来保存增量*/
/*睡眠进程列表*/
抢占=量子;/*初始时间量子*/
/*指定seepq最初为空*/
slnonempty=FALSE;
clktime=0;/*开始计算秒数*/
/*设置为:定时器0,16位计数器,速率发生器模式,
计数器是二进制的*/
outb(CLKCNTL,0x34);
/*必须先写入LSB,然后写入MSB*/
outb(时钟0,(字符)intv);
outb(时钟0,intv>>8);
返回;
}
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;
}
/*clkhandler.c-clkhandler*/
#包括
/*------------------------------------------------------------------------
*clkhandler-处理时钟中断和处理抢占事件
*以及唤醒睡眠的过程
*------------------------------------------------------------------------
*/
中断clkhandler(无效)
{
clkupdate(每刻度CLKCYCS);
/*记录时钟滴答声*/
clkticks++;
/*更新全局计数器秒*/
如果(clkticks==clkticks\u/秒){
clktime++;
clkticks=0;
}
/*如果睡眠队列为非空,则减少第一个键;当*/
/*键达到零,唤醒一个睡眠过程*/

如果(nonempty(sleepq)&&(-firstkey(sleepq)
intv
是用于调度的中断计时器的时间切片粒度(以Khz为单位)(至少在此代码中是如此)。每5秒听起来非常慢,可能会使系统几乎没有响应,请尝试毫秒的顺序

要计算新的间隔,您需要更改此值并对频率进行一点计算。您可能可以通过在
intv
上进行的计算得出这一步,以获得10ms


在x86中,可以通过使用
outb
汇编指令将计时器中断值(KHz)写入端口
0x40
来建立计时器值。如代码所示,您必须先写入最低有效字节,然后再写入最高有效字节(
outb
一次写入一个字节)。若要启用计时器,请将
0x36
写入同一端口,并且必须将IRQ处理程序绑定到IRQ0才能接收中断。我尝试为您压缩一点信息,但这是x86特定的。

我甚至不明白更改intv的值将如何影响任何事情。据我所知,它在其他任何地方都没有使用。我发现一个clkhandler.c,我可以计算所经过的时间并在那里调用我的函数吗?我在上面添加了它。@blackdemon619这是因为它是一个严格的中断计时。您可以通过更改中断计时器的值来更改计时。@blackdemon619如果您想了解更多,我已经编写了自己的操作系统,您可以看看我是如何做到的关于这一点(同样是针对x86的),我在提供的.S文件的comments部分看到clktime表示启动后的秒数。如果我检查(clktime%4==0),我能有效地在中断clkhandler中每4秒调用一次吗?@blackdemon619是的,我不建议只安排每4秒一次,但是,你必须记住USB设备是基于轮询的,如果事情长时间运行而没有中断,你就永远没有机会检查设备状态,因此你的系统看起来非常不正常海绵