Forth-83 多任務解析

      FORTH 系統能夠寫多任務,是因爲 FORTH 語言是集操做系統、編譯程序、彙編程序等於一體的具備可擴充性的十分靈活的工具。
       用戶變量及用戶區:
一個做業或一個任務是在必定的程序環境中運行的。一個任務運行了一段時間而讓給另外一個任務以前,首先必須把當前任務的運行環境保存起來,以便之後該任務再次得到 CPU 時得以繼續運行。FORTH 系統使用一組變量跟蹤,記錄和保存當前程序運行環境。存放用戶變量的值的 FORTH 存貯區域叫作用戶區。每個任務須要的用戶變量以下:
變量名 意義
TOS 指向參數堆棧頂
ENTRY 當任務被激活時轉移的入口點
LINK 指向下一個任務
SP0 參數堆棧的起始地址
RP0 返回堆棧的起始地址
DP 詞典的頂部
#OUT 已發送的字符數
#LINE 已打印的行數
OFFSET 當前文件的塊位移
BASE 當前在輸入/輸出轉換中採用的數制
HLD  (- addr) 指向在 PAD 區中剛轉換完的字符
FILE 指向當前文件的 FCB
IN-FILE 指向輸入文件的 FCB
PRINTING 打印機狀態標誌,其值爲真時,打印機處於激活狀態
  一、這些 變量的名字存在於主詞典中(他們隸屬於 FORTH 詞彙),可是 它們的數值卻保存在用戶區中。每一個用戶有本身單獨的用戶區及以上變量的付本。也正是由於這些重要的信息是由各個任務自身單獨保存着的,因此任務之間的轉換就變得很容易了,僅僅只有解釋指針 IP 的值等三個別的信息須要在任務轉換中顯示保存。
    二、 用戶變量並不使用參數域地址做爲地址,而是使用在當前任務的用戶區中該變量距用戶區首地址的相對位移來編址。每一個用戶有本身單獨的用戶區,在用戶區內的用戶變量的數值描述了該任務在任一時刻的運行環境。在終端上以交互方式運行的任務的用戶區的起始地址能夠方便地用 UP@ 獲得,它所指着的用戶區也就是系統生成時所劃定的用戶區域。在多任務環境中,每新建一個任務都要給它指定一塊用戶區。
      
       暫停及從新開始:
堆棧 功能
(PAUSE) ( - ) 中止當前任務的執行,把控制轉交給下一個任務。

它把 IP 及 RP 存放到參數堆棧上,把參數堆棧指針存進用戶變量 TOS 中,轉移到由 LINK 所指着的代碼,從而實現多任務轉換。
RESTART ( - ) 與(PAUSE)相反。取回所存放的信息,執行在上一輪暫停的任務
SLEEP ( addr -  ) addr 是任一用戶區的首地址,SLEEP 使該任務永遠暫停
WAKE ( addr -  ) 喚醒一個在"睡覺"的任務,使它在下一次輪到時運行
STOP ( - ) 永遠暫停當前任務
PAUSE ( - ) 在多任務環境中 PAUSE 執行 (PAUSE)
    F83 採用輪轉法進行多任務調度,其中最關鍵的兩個詞是 (PAUSE)RESTART(PAUSE)顯示存放當前任務的 IP返回堆棧指針以及 參數堆棧指針,而後執行轉移指令轉移到下一個任務的 ENTRY RESTART 把下一任務的用戶變量 TOS 的地址送入 UP 恢復所保存的參數堆棧指針,返回堆棧指針及解釋指針IPIP 指着該任務在暫停以前所要執行的下一個詞,RESTART 最後執行 NEXT,因而所恢復的任務就繼續執行。
:  STOP   ( - )    
        UP  @     返回當前任務的地址
        SLEEP      使當前任務「睡覺」
        PAUSE  ;  當即中止當前任務而開始執行下一個任務
CODE PAUSE
      NEXT
END-CODE 

在單任務運行方式下,PAUSE 當即返回什麼也不作;但在多任務方式中,把(PAUSE)的代碼指針域的內容填入到 PAUSE 的代碼指針域中,因而一個任務執行到 PAUSE 時就暫停下來。

    多任務的創建:
    首先必須把一個任務定義爲詞典中的一個詞,與此同時分配給它做爲 用戶區、參數堆棧、返回堆棧及詞典區的主存區域。另外,還必須把它鏈入到輪轉法調度循環中。上面這些工做均由定義 TASK: 承擔。
堆棧 功能
#USER (- addr) 存放在用戶區大小的變量
@LINK (- addr) 給出下一任務的ENTRY的地址
!LINK   (addr -) 把一相對距離賦給當前任務的 LINK。使之 LINK+(LINK) 等於下一任務用戶區的首地址
LOCAL (base addr - addr1) base爲下一任務用戶區的首地址,addr 爲本任務之某一用戶變量的地址,addr1是下一任務的同一用戶變量的地址。
SET-TASK (ip addr -) 使地址爲addr的任務執行由ip指着的代碼

:  TASK:    ( size   -  )   創建一個新任務和作有關的初始化工做(size   -)  // size 表示詞典空間大小
          CREATE   創建新任務的首部
          TOS         當前任務用戶區首址
          HERE       新任務的用戶區今後處開始
          #USER @    取出用戶區的大小           (size   當前用戶區首址   新任務用戶區首址   用戶區大小   - )
          CMOVE   把現行任務的用戶變量複製給新任務,初始化新任務的用戶區     (size   -)
          @LINK     新任務的 ENTRY 的地址      (size   新任務入口地址   -)
          UP @ -ROT   把當前任務的用戶區指針送到堆棧低暫存    (當前用戶區起始地址   size   新任務入口地址    -)
          HERE UP !  使 UP 指向新任務的用戶區    (當前用戶區起始地址   size   新任務入口地址    -)
          !LINK       把現行任務用戶區的地址存入到新任務的 LINK 中  (當前用戶區起始地址   size   -)
          DUP HERE +    新用戶區及size之和的下一地址   (當前用戶區起始地址   size   新用戶區和size和的下一個地址   -)
          DUP RP0 !        初始化新任務的返回堆棧指針      (當前用戶區起始地址   size   新用戶區和size和的下一個地址   -) 
          100 - SP0 !       初始化新任務的參數堆棧指針      (當前用戶區起始地址   size  -)
          SWAP UP !        恢復 UP 指向現行任務           (size  -)
          HERE ENTRY LOCAL !LINK                把新任務的地址存進現行任務的 LINK 中   (size  -)
          HERE #USER @ +    新任務詞典區首地址       (size  新任務詞典區首地址  -)
          HERE DP LOCAL !    初始化新任務詞典指針   (size  -)
          HERE SLEEP       首先使新任務處於"睡眠"狀態       (size  -)
          ALLOT ;       分配 size 個字節給新任務      (-)
TASK:  完成一個新任務在詞典中的創建和有關的初始化工做,但該新任務尚未被賦予具體的工做。賦予具體的新任務的工做由定義   BACKGROUND:  承擔。在 F83 中能夠定義不少個"後臺做業"和一個"前臺做業",後臺做業的執行通常不佔終端,而把前臺留給使用者運行前臺做業和檢查後臺做業的執行狀況。這個前臺做業和全部後臺做業在一塊兒按輪轉法調度就造成了 F83 的多任務環境,使得多個任務能夠共同執行。
:  BACKGROUND:    ( - )     創建一個詞典空間爲 400 個字節的新任務,初始化該任務去執行跟着的代碼
         400  TASK:        創建一個以跟着的名字命令的新任
         HERE  IP            指向有待編譯的代碼,使得新任務能夠執行它     新任務地址  當前解釋指針位置  - )
         @LINK  2-         新任務的地址      (新任務地址  當前解釋指針位置  新任務入口地址-2  -)
         SET-TASK          初始化新任務,讓她執行 IP 指着的代碼  (新任務地址  -  )
         !CSP            編譯程序查錯初始化       
         ]  ;                調用編譯程序,編譯要爲新任務執行的跟着的代碼    


多任務調度:
    分時操做系統按照輪轉法調度來自多個終端上的多個做業:它讓每一個做業每次運行必定的時間,時間一到就經過中斷把 CPU 轉讓給下一個做業。F83 也是採用輪轉法調度多任務的運行,不過不是經過中斷,而是經過多個任務的主動合做和協調來實現;這樣,在 F83 中就不須要有專職的調度程序。 在多任務的環境中詞 PAUSE 的功能是中止當前任務的執行,把對 CPU 的控制轉交給下一個任務。在 F83 的每一共行任務中,每隔適當的間隔就得安插上一個 PAUSE , 以便讓其它的任務有機會投入運行。不然一個任務就會獨佔 CPU , 共行執行就將沒法實現;另外一方面, 當一個任務須要 CPU 時,它將把 WAKE 代碼放進他的用戶變量 ENTRY 內,這樣當下一輪對 CPU 的控制傳給它時,該任務即可以繼續執行。F83 中的多任務要具備相互合做的性質,這樣作的優勢是使每一個任務的起點、停點均爲已知,並使得多任務的調度簡單和迅速。F83 各共行任務的連接是依靠用戶變量 LINK 。
堆棧 功能
MULTI (-) 創建多任務調度循環
SINGLE (-) 取消多任務調度循環

MULTI 在多任務調度中相當重要,它把(PAUSE)的代碼指針域的內容放入 PAUSE 的代碼指針域,這樣就使得但凡含有 PAUSE 的任務執行到 PAUSE 時就暫停。MULTI 又把 RESTART 的代碼指針域的內容放入到中斷向量表中編號爲 80H 的項目的第一個單元。此後,但凡 ENTRY 內含有 INT 80H 的任務輪轉到時就可投入運行。

:  SINGLE    ( - )
       [']  PAUSE  >BODY
       [']  PAUSE  !  ;
定義中的第一行返回 PAUSE 的 pfa ,它指向 NEXT 。注意:PAUSE 是 CODE 定義,CODE 詞的代碼指針域內的內容是其參數域地址。定義第二行恢復 PAUSE 的代碼指針域爲常態。這樣 PAUSE 就將當即返回而再也不執行(PASE)


     F83 中是用詞 BACKGROUND: 定義一個新任務,它把一個任務的首部定義爲一個變量,所以引用一個任務的名字就在參數堆棧上留下該任務的參數域地址,而它就是一個任務的用戶區的首地址。所以, 鍵入一任務名 SLEEP 就把 JMP NOP 的代碼存入該任務的 ENTRY 中,從而使任務處於「睡眠」狀態。而鍵 入一任務名 WAKE 就把 INT 80H 的代碼存入任務的 ENYTRY 中,因而在下一輪中輪到時就投入運行。在一個任務的創建過程當中,同時也把它加入到多任務鏈中, 一個任務的用戶變量 LINK 自己的地址與 LINK 單元的內容之和老是指向鏈中的下一個任務。用這種方法把一個前臺做業和多個後臺做業彼此間連接起來 。
      多任務調度循環由定義 MULTI 創建。所以在執行多任務以前首先要執行 MULTI 執行 MULTI 激活 PAUSE,同時又把 RESTART 的地址送進中斷向量表第 80H 項。而一個任務一旦被「喚醒」,它的用戶變量 ENTRY 的內容就是 INT 80H ,而 ENTRY 的內容正是一個任務要執行的第一條指令。因而輪到該任務執行時就產生編號爲 80H 的軟中斷,接着就轉去執行 RESTART , 恢復該任務上次暫停時的環境,接着繼續運行。因爲每一個任務有本身單獨的用戶區,在那兒保存着它自身運行環境,因此任務間的轉換就至關簡單。前臺任務使用的用戶區就是詞典中原有的用戶區,而每一個後臺做業的用戶區及其餘專用區域則在創建任務時加以指定。
相關文章
相關標籤/搜索