【问题标题】:Modify clock interrupt handler xinu修改时钟中断处理程序xinu
【发布时间】:2013-03-19 22:11:17
【问题描述】:

我今晚有一个操作系统项目,需要澄清一个主题。我们正在使用操作系统 XINU。我正在尝试更改默认的操作系统调度程序以解决某些进程被饿死的问题。我被引导到 clkint.S 文件,我认为它是时钟中断处理程序。我的问题是,我怎么知道它中断的频率?如何设置时间让我们说每 5 秒调用一次函数?我查看了 intel 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

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;
}

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;
}

我可以自己添加所有的饥饿功能,我只需要弄清楚如何让 clkint.s 处理程序调用我的函数让每 5 秒说一次...我不明白时钟是如何工作的或完全组装。我不是要求有人给我解决方案,我只是需要一些指导。

【问题讨论】:

    标签: assembly operating-system x86 interrupt


    【解决方案1】:

    intv 是用于调度的中断定时器的时间分片粒度(单位为 Khz)(至少在此代码中)。每 5 秒听起来很慢,可能会使您的系统几乎没有响应,请尝试以毫秒为单位。

    要计算新的间隔,您需要更改此值并对频率进行一些数学运算。您可能可以从 intv 上完成的计算中算出这一步,得到 10 毫秒。

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

    【讨论】:

    • 我什至不明白改变 intv 的值会如何影响任何事情......据我所知,它没有在其他任何地方使用。我找到了一个 clkhandler.c,我可以计算经过的时间并在那里调用我的函数吗?我在上面加了。
    • @blackdemon619 那是因为它的中断时间很严格。您始终可以通过更改中断计时器的值来更改时间。
    • @blackdemon619 如果您想了解更多信息,我已经编写了自己的操作系统,您可以看看我是如何做到的(同样针对 x86)github.com/jesus-ramos/not-a-good-os/blob/master/kernel/timer.c
    • 我看到 clktime 在提供的 .S 文件的 cmets 部分中显示自启动以来的秒数。如果我检查 if (clktime % 4 == 0),我可以在中断 clkhandler 中每四秒有效地调用一次吗?
    • @blackdemon619 是的,我不建议只每 4 秒安排一次,你必须记住 USB 设备是基于轮询的,如果事情长时间运行而没有中断,你永远没有机会检查设备状态所以你的系统会显得非常迟钝。您是否有理由要以 4/5 秒的粒度执行此操作?这是很多 CPU 周期
    猜你喜欢
    • 2023-03-08
    • 2011-07-20
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多