【学習メモ#10th】12ステップで作る組込みOS自作入門

1,308 views

Published on

12ステップで作る組込みOS自作入門
http://www.amazon.co.jp/dp/4877832394/
坂井 弘亮(著)
カットシステム

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,308
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

【学習メモ#10th】12ステップで作る組込みOS自作入門

  1. 1. 12ステップで作る組込みOS自作入門 10thステップ @sandai
  2. 2. 【参考書籍】12ステップで作る組込みOS自作入門【内容】1ステップずつ、実際に動かしながらプログラムを発展させていく方式で無理なく学べる。OSやハードウェアに詳しくない方にも理解できるように十分な説明を提供坂井 弘亮(著)カットシステム(2010/5)【税込価格】4,410円【サポートページ】http://kozos.jp/books/makeos/
  3. 3. もくじ1.OSの役割2.メモリ管理3.メモリ管理実装4.プログラムの実行5.まとめ
  4. 4. 1.OSの役割
  5. 5. コンピュータの3大要素● コンピュータの3大要素は以下の3つ – CPU – メモリ – I/O
  6. 6. ノイマン型コンピュータ● プログラムをメモリ上に配置し、CPUがメモリ 上のプログラムを逐次実行することで処理を進 めていくコンピュータをノイマン型コンピュー タと呼ぶ● このようにCPUとメモリは必ず必須の要素であ り、処理の結果を出力したり入力を得るために はI/Oが必要● 前のページで挙げた3つの要素を管理していく のがOSと言える
  7. 7. CPU時間● CPUを管理するというのは、つまり複数のタス クに対してCPUを割り当てる時間を配分すると いうこと● CPUをタスクに割り当てて処理している実行時 間をCPU時間と呼ぶ● スレッドの目的はこのCPU時間を複数のタスク に自動で配分するため● スレッドを実装することでCPUが処理している のは自分だけであるかのように、独立してアプ リを書くことができる
  8. 8. 2.メモリ管理
  9. 9. メモリの衝突● 動作しているプログラムによってメモリを使い 分けないと、複数のスレッドで同じアドレス位 置のメモリを使ってしまう可能性が出てくる – メモリの値が衝突して正しく処理できない● そこでメモリのアドレスを管理しなくてはなら ない● メモリの管理には静的なメモリ管理(static)と 動的なメモリ管理(dynamic)がある
  10. 10. 静的なメモリ管理(static) メモリ領域を固定で割り当て、実行ファイルの 作成時に配置を決めてしまうこと● たとえばリンカ・スクリプトを利用すること で、そのようにメモリ領域を固定で割り当てる ことができる● この方法は必要なときに獲得するとか不要に なったら解放するとか、解放された領域を使い まわすといったことができない
  11. 11. 動的なメモリ管理(dynamic)● プログラムの動作中にメモリの獲得と解放を行 うようなメモリ管理の仕方● メモリの獲得動作をアロケート、開放処理をフ リーと呼ぶ● 動的なメモリ管理としては他にスタックがある が、階層的な構造で自由に獲得/解放は行えな い
  12. 12. メモリ保護● C言語の標準ライブラリにはmalloc()やfree() という関数があって、動的にメモリを獲得/解 放することができる● メモリを勝手に使うのではなく、このような サービス関数を利用すれば衝突の問題はない – 関数内部でメモリ管理が行われるため● 汎用OSでは複数のプログラムが互いに利用して いるメモリを破壊しないよう、それぞれメモリ 保護する機能が必須
  13. 13. メモリ管理● メモリ管理には大きく次の2つに分けられる – 可変サイズのメモリ管理 – 固定サイズのメモリ管理● 可変サイズのメモリ管理はmalloc()で実装され ているメモリ管理方法 – 自由なサイズのメモリを獲得することが可能● C言語でメモリを動的に利用するならmalloc() やfree()を利用するのが一般的である
  14. 14. malloc()でのメモリ管理● 独自にmalloc()を実装するにはどうすべきか、 malloc()と似た方法で可変サイズの領域を切り 売りする方法を考えてみる● まず固定サイズの領域を確保 – char memory_area[128*1024]● 固定サイズの領域を確保して、これを静的変数 として可変サイズで利用する – 大きな枠を固定して、そのうちを可変で利用するっ て感じ● malloc()で可変サイズのメモリ領域を獲得する ときは、memory_area[]から切り出す● 切り出し用のメモリはメモリ・プールと呼ぶ
  15. 15. 可変サイズでのメモリ管理1● メモリ管理の方法として、小さいアドレスから 順に切り出していく方法で考えてみる● このような管理方法だと各領域 をfree()で解放しても再利用で きない 10 – そもそも領域のサイズをデー タとして持っていないので 15 free()は使えない 10● メモリ領域をたんに切り出して 分け与えるような方法ではうま 20 くいかない
  16. 16. 可変サイズでのメモリ管理2● そこで、領域のサイズや獲得済み・ ヘッダ 解放済みなどの情報をヘッダとして 10 領域の先頭に付加させてみる ヘッダ● 領域の獲得時はヘッダにサイズなど 15 の情報を書き込み、ヘッダの直後 ヘッダ にある実際の利用領域の先頭アドレ 10 スを返す ヘッダ● 解放時には、free()の引数として与 えられた領域から逆算すれば、ヘッ 20 ダの位置を知ることができる● が、これだとまだ小さいアドレスか ら順に切り出すしか方法がない
  17. 17. 可変サイズでのメモリ管理3● そこでnextポインタをヘッダに持たせて獲得し た領域と解放した領域をリンクリスト管理する● こうすることで、解放後 ヘッダ の領域の検索が可能のな 10 るため、再利用すること ヘッダ ができる 15● malloc()するときには、 まず解放済みのリンクリ ヘッダ 10 ストを検索して、無けれ NULL ヘッダ ばメモリ・プールから切 り出すといったことがで 20 NULL きるようになる
  18. 18. 可変サイズでのメモリ管理4● 今回の例はnextポインタによる片方向リンク だったが、実践的にはnextポインタとは逆方向 の前方ポインタも持たせる – リンクリストの途中からの抜き出しなどのため – 前方ポインタはprevと使うことが多い● nextとprevの両方を持つリンクリストを双方向 ンクと呼ぶ● 双方向リンクで管理された可変サイズのメモリ 領域を一般にヒープ領域と呼ぶ
  19. 19. 可変サイズでのメモリ管理5● 実際には、この他に解放済み領域を再割当てす る際にも必要サイズを切り出したり、隣接する 解放済み領域の統合や、メモリ・プールも解放 済みのリンクリストにつなげたりする● リンクリスト管理の欠点としては、獲得と解放 を繰り返すうちにメモリが細分化されすぎてす まうこと – フラグメンテーションと呼ぶ● とりあえず、今のとこはリンクリスト管理する ことで、可変サイズのメモリの割り当てと解放 ができる、と理解しておけばよい
  20. 20. 可変サイズでの管理の欠点● リンクリスト管理する場合、メモリ獲得時に検 索処理が必要となる● 検索で見つかるまでの時間がどれぐらいかかる か、保証ができない – リアルタイムOSだとこれは致命的● たとえリアルタイム性を求めないにしても、組 込み処理では検索のような時間のかかる処理は 適切でない● 動的にメモリを管理する場合、可変サイズは使 用効率は良いが向いていない
  21. 21. 固定サイズでの管理● そこで固定サイズでのメモリ管理を行う● 最初からいくつかサイズに分けたメモリ領域を 確保し、メモリ領域の獲得時には必要とされる サイズが入りきる固定領域を与えるようにする – 10バイトの領域が必要なら16バイド領域、40バイト の領域が必要なら128バイトを与える形式● メモリ・プールの未獲得領域はサイズごとにリ ンクリストにして管理する● メモリ獲得時にはリンクリストの先頭の領域を 割り当て、解放された領域は再びリンクリスト に接続する – メモリ使用効率は悪いが、検索するよりリアルタイ ム性は確保できる
  22. 22. 3.メモリ管理の実装
  23. 23. プログラムの修正と追加● 追加ファイル – memory.h,memory.c...メモリ管理ライブラリ – test10_1.c...メモリ管理サンプル● 修正ファイル – ld.scr...メモリ・プール追加 – syscall.h,syscall.c...システム・コール追加 – kozos.h,kozos.c...システム・コール追加 – main.c...起動するスレッドを修正 – Makefile
  24. 24. プログラムの修正内容● メモリ管理を実装 – 自由に使っていいメモリの領域(メモリ・プール)を 用意して、必要になったらそこから切り出して使え るようにしている – 再利用しやすいように、メモリ管理はリンクリスト 管理で行う – 事前に16バイト、32バイト、64バイトずつに分けて おいた領域をそれぞれいくつか用意し、ヘッダを付 けて片方向リンクでつなげる
  25. 25. kzmem_init_pool()static int kzmem_init_pool(kzmem_pool *p){ int i; kzmem_block *mp; kzmem_block **mpp; extern char freearea; static char *area = &freearea; mp = (kzmem_block *)area; mpp = &p->free; for(i = 0; i < p->num; i++) { *mpp = mp; memset(mp, 0, sizeof(*mp)); mp->size = p->size; mpp = &(mp->next); mp = (kzmem_block *)((char *)mp + p->size); area += p->size; } return 0;}
  26. 26. メモリ・プールの初期化の流れ1● mp = (kzmem_block *)areaでkzmem_block構造 体をarea番地に作成しmpに代入● mpp = &p->freeは、freeポインタはメモリ・ プールの先頭にあたる。メモリを獲得するとき はここからバイト別に合わせて取得するように なる。mppにはその先頭アドレスを代入● 次にfor文があるが、ここはメモリブロックを 作成しつつnextポインタをつなげている処理 – mmpダブルポインタを利用しているため複雑に感じ るが、ポインタを理解してさえいればどうなってい るか分かる
  27. 27. メモリ・プールの初期化の流れ2● 最初の*mpp = mpは&p->free = mpと同じこと – for文の2週目からはmp->next = mpと同じ● memset()で0クリアして、mp->sizeにブロック の大きさを代入● mpp = &(mp->next)で次のmpのnextポインタに 進む● mp = (kzmem_block *)((char *)mp + p- >size)で新しいkzmem_block構造体を定義● area += p->sizeは今回のプログラムでは関係 がないけれど、他のメモリ・プール初期化関数 がある場合にはこうして未使用領域の先頭を保 持しておく必要がある
  28. 28. メモリの獲得と解放● 獲得 – 必要なサイズに収まるメモリブロックを探し て、先頭のブロックを引き抜くだけ – return mp + 1のように、メモリヘッダの後 続のデータ領域を渡すようにする● 解放 – 解放というか、使っているメモリブロックを リンクリストの先頭に戻すだけみたい – ゼロクリアとかしてないけど、要らないのか な
  29. 29. メモリブロックの大きさ● 今回のプログラムでは16バイト、32バイト、64 バイトのメモリブロックをそれぞれ別々にリン クして複数個作っている● 16バイトのうち、8バイトはメモリヘッダなの で、16バイトのブロックは実質8バイトしか使 えないし、64バイトでも実質56バイトしかつか えない● 書籍では大きく取り上げていないけれど(さ らっと書いてる)、そういうわけなので、実質 的なデータ領域がいくつかということは把握し ておこう
  30. 30. 4.プログラムの実行
  31. 31. プログラム実行/Users/sandai/12step/src/10/os% sudo cu -l /dev/tty.usbserial-FTG6PQ4H..00ffd178 aaa00ffd188 bbb00ffd188 aaaaaaa00ffd178 bbbbbbb00ffd1f8 aaaaaaaaaaa00ffd218 bbbbbbbbbbb00ffd218 aaaaaaaaaaaaaaa00ffd1f8 bbbbbbbbbbbbbbb00ffd1f8 aaaaaaaaaaaaaaaaaaa...00ffd338 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa00ffd2f8 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb00ffd2f8 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa00ffd338 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb00ffd338 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa00ffd2f8 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbtest10_1 exit.test10_1 EXIT.
  32. 32. 5.まとめ
  33. 33. まとめ● 簡単なメモリ管理を実装した● 他にもいくつか手段があるが、考え方は似たよ うなものらしいので、きっちり理解しておきた い部分● ダブルポインタに苦戦した。なんとなくポイン タ理解してるぐらいじゃだめだ。理解したらほ んと単純なものなんだけど

×