2: 2007-01-26 (金) 14:08:38 |
現: 2024-01-06 (土) 22:39:13 |
| -tssの作成と登録の実際 | | -tssの作成と登録の実際 |
| struct TSS32 tss_a,tss_b; /*構造体として親切する | | struct TSS32 tss_a,tss_b; /*構造体として親切する |
| + | |
| tss_a.ldtr = 0; /*ldtrとiomapはとりあえずこの数値にする。 | | tss_a.ldtr = 0; /*ldtrとiomapはとりあえずこの数値にする。 |
| tss_a.iomap = 0x40000000; | | tss_a.iomap = 0x40000000; |
| tss_b.ldtr = 0; | | tss_b.ldtr = 0; |
| tss_b.iomap = 0x40000000; | | tss_b.iomap = 0x40000000; |
| + | |
| /*gdtへの登録 | | /*gdtへの登録 |
| set_segmdesc(gdt + 3,103,(int) &tss_a,AR_TSS32); /*それぞれ、GDT3番と4番に | | set_segmdesc(gdt + 3,103,(int) &tss_a,AR_TSS32); /*それぞれ、GDT3番と4番に |
| P296の初期設定 | | P296の初期設定 |
| tss_b.eip = (int) &task_b_main; /* 関数task_b_mainの先頭アドレス | | tss_b.eip = (int) &task_b_main; /* 関数task_b_mainの先頭アドレス |
- | | + | |
| + | |
| /* これはtask_b専用のスタックの設定。mamman_allocと使い64kbを確保。 | | /* これはtask_b専用のスタックの設定。mamman_allocと使い64kbを確保。 |
| /* 後ろの計算式はスタックの最終番地を計算したもの | | /* 後ろの計算式はスタックの最終番地を計算したもの |
| task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024; | | task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024; |
| tss_b.esp = tssk_b_esp; | | tss_b.esp = tssk_b_esp; |
- | | + | |
| + | |
| tss_b.eflags = 0x00000202; /*??? どういう意味だ? | | tss_b.eflags = 0x00000202; /*??? どういう意味だ? |
| + | |
| tss_b.eax = 0; /* 通常の各レジスタの初期値。 | | tss_b.eax = 0; /* 通常の各レジスタの初期値。 |
| tss_b.ecx = 0; | | tss_b.ecx = 0; |
| ***P298のタスク戻し [#abc9a649] | | ***P298のタスク戻し [#abc9a649] |
| -これは説明するまでもない。解る。 | | -これは説明するまでもない。解る。 |
| + | |
| + | COLOR(red){''疑問点:''タスクはかならずしもメモリを別セグメントにして動かすとは限らないことが上記の簡易切り替えで解った。そうなるとメモリ用に1個として、理屈ではタスクは8,190個以上は絶対に作れないということでOKなのか?} |
| + | |
| + | ***自動的にタスクを行き来 [#yf41a433] |
| + | -P300のソースはわかりやすい。HariMainがtask_a。task_b_mainはtask_bと見る。 |
| + | -実際のソースよりすこし整理して端折ったソースを載せる。 |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | void HariMain(void) |
| + | { |
| + | (中略) |
| + | |
| + | /*タイマー timer_tsを新設。*/ |
| + | struct TIMER *timer, *timer2, *timer3, *timer_ts; |
| + | |
| + | (中略) |
| + | |
| + | /*新設したタイマーを初期化*/ |
| + | timer_ts = timer_alloc(); |
| + | timer_init(timer_ts, &fifo, 2); /* タイムアウトしたら「2」をFIFOに送るよう設定 |
| + | timer_settime(timer_ts, 2); /* タイムアウト時間を0.02秒に設定 |
| + | |
| + | (中略) |
| + | |
| + | /* 上記は設定。ここ以下のforループがtask_aの本質部分*/ |
| + | for (;;) { |
| + | |
| + | (中略) |
| + | /* FIFOに2が来たら(timer_tsがタイムアウトしたら */ |
| + | if (i == 2) { |
| + | farjmp(0, 4 * 8); /*タスクをtask_bに切り替える |
| + | timer_settime(timer_ts, 2); /*ここに復帰した時、再度タイマーをセットする |
| + | } else if (256 <= i && i <= 511) { /* キーボードデータ */ |
| + | |
| + | (中略) |
| + | |
| + | } |
| + | |
| + | |
| + | void task_b_main(void) |
| + | { |
| + | struct FIFO32 fifo; /*これら構造体は、タイマーを使う |
| + | struct TIMER *timer_ts; /*ために必要なもの。 |
| + | int i, fifobuf[128]; |
| + | |
| + | fifo32_init(&fifo, 128, fifobuf); /*FIFOを初期化して準備する。 |
| + | timer_ts = timer_alloc(); /*そうしないとタイマーが使えないから |
| + | timer_init(timer_ts, &fifo, 1); /*タイムアウトすると1を返してくるタイマー。 |
| + | timer_settime(timer_ts, 2); |
| + | |
| + | for (;;) { |
| + | |
| + | (中略) |
| + | |
| + | i = fifo32_get(&fifo); /*FIFOから一つ数値を得る。 |
| + | io_sti(); |
| + | if (i == 1) { /* タスクスイッチ */ /*もしその通知が1ならタスクスイッチ! |
| + | farjmp(0, 3 * 8); |
| + | timer_settime(timer_ts, 2); |
| + | |
| + | } |
| + | } |
| + | } |
| + | } |
| + | |
| + | -・・・だめだ・・・P304がどうしても理解できない・・・・orz |
| + | |
| + | -「とにかくこの方法でsht_backの値をtask_b_mainに渡せる」と理解しておこう。(これ以上は無理) |
| + | --ただ、一つ解ったことがある。 |
| + | --通常、別のタスク(task_bとか)には、それ用のtssと同時にそれ用のスタックが必要。(そらそーだ。分けないとごっちゃごちゃになっちゃう) |
| + | --別のタスクになにも変数を渡す必要がない場合。(たとえば void task_b_main() なんて場合) |
| + | -- task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024; |
| + | --こんなことして、task_b用のスタックを確保している。おそらく、大半のタスクでもこれは必要な行為だろう。(スタックを一切使用しない動作だけのタスクとかそういう特殊なのは別ね) |
| + | --それに対して、今回はようするに、task_bに対して値を渡したいというだけ。 |
| + | --で、task_bは引数を持つ関数になっている。(void task_b_main(struct SHEET *sht_back); ) |
| + | --普通に関数を呼ぶだけならなんの問題もない。そのまま呼べばよい。 |
| + | --しかし、今回の相手は「別に動くタスク」だ。なので、呼び出しで引数を渡せない |
| + | --しかし、今回どうしても理解できなかった部分の登場となる。いまだにわからない。 |
| + | --・・・しかし、このわからない部分は、 |
| + | -- task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024 -8; |
| + | --である。普通に用意するスタックから 8 を引いているだけだ。 |
| + | --これがヒントになるかもしれない。いずれ解るかも。 |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | ***自動タスクスイッチ [#i203f197] |
| + | -上記のソースを見ての通り、これまではお互いのタスクが相手のタスクに切り替わるという動作をしていたが、こういうプログラム部をなくしてもフルオートで切り替えが出来ないものだろうか? |
| + | |
| + | -タスクスイッチ専用の特殊なタイマーを1個確保したと考えればよい。 |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | COLOR(Blue){''疑問点解決?:''タスクはかならずしもメモリを別セグメントにして動かすとは限らない(上記参照)。また、状況によってはtssを共有することすら可能。(タスクA,B,Cとあった場合、絶対tssが3個必要というわけではない。屁理屈チックだが、タスクAとタスクCが絶対同時に動かないような調整をすればtssは2個でも十分マルチタスクは可能)よってこの場合は、タスクではなく''tssはどう頑張っても8,190個以上は作れない''ということでOKのようだ。(・・・なんかあったりまえな答えになってしまったな・・・(^^;))} |