1

今夜締め切りのオペレーティング システム プロジェクトがあり、あるトピックについて説明が必要です。オペレーティングシステムXINUを使用しています。一部のプロセスが不足していることを考慮して、デフォルトの OS スケジューラを変更しようとしています。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 秒ごとに A と言ってください...時計の仕組みやアセンブリがわかりません全体的に。誰かに解決策を求めているわけではなく、ただガイダンスが必要なだけです。

4

1 に答える 1

2

intv(少なくともこのコードでは) スケジューリング用の割り込みタイマーのタイム スライスの粒度 (Khz 単位) です。5 秒ごとは非常に遅く聞こえ、システムの反応が鈍くなる可能性があります。ミリ秒単位で試してください。

新しい間隔を計算するには、この値を変更し、頻度を少し計算する必要があります。intvおそらく、10ms を取得するために行われた計算から、このステップを理解することができます。

x86 では、アセンブリ命令0x40を使用してKHz 単位のタイマー割り込み値をポートに書き込むことにより、タイマー値を確立できます。outbコードに示されているように、最下位バイトに続いて最上位バイトを書き込む必要があります (outb一度に 1 バイトずつ書き込みます)。タイマーを有効にする0x36には、同じポートに書き込み、割り込みを受け取るために IRQ ハンドラーを IRQ0 にバインドする必要があります。情報を少し要約してみましたが、これは x86 固有のものです。

于 2013-03-19T22:15:40.203 に答える