pubDate: 2024-05-30
author: sakakibara
スレッドの切替時にはコンテキストスイッチが発生する。
コンテキストスイッチとは、 CPUのレジスタに含まれる情報 (プログラムカウンタ、スタックポインタ、汎用レジスタ)を メモリの特定の場所 に保存し、後で復元すること(機構)である。
コンテキストスイッチは2つの手段に分かれる。
コントロールブロックとはOSがプロセスやスレッドの状態を管理するために使用するデータ構造である。 コントロールブロックは以下の2つに分けられる。
PCBに保存される内容としては
TCBに保存される内容としては
サブルーチンと関数は同じ意味で、特定のタスクを実行するための自己完結型のコードブロックである。
対して、コルーチンは、サブルーチンと異なり複数のエントリポイントを持ち、実行状態を保持して再開することのできるプログラム構造である。 制御ポイントを移動さえるにはyieldを使う。
サブルーチンとコルーチンの違いとしては
yield
を使って、途中で一時停止し、再開することができる。コルーチンはどうやって関数の状態を保存しているのか? コルーチンが実行されると、その状態をコンテキストとしてメモリに保存する。
スレッドの状態は(TCBなどにして)OSが管理し、コルーチンの状態はユーザーが管理する。 このため、コルーチンは軽量スレッドと言われる。
killなどはプロセスに対してシグナルを送信する。 シグナルとはプロセスに対してOSが通知するためのメッセージ・メカニズムである。 シグナルはプロセスに何か特定の状況が起こったことを発生したことを通知するために使用される。 割り込み、エラー、プロセスの終了などが該当する。 プロセスはシグナルを受信した際にどのようにシグナルをハンドリングするか、どのような関数を定義して応答するかを決めることができる。 たとえば、プロセスの終了、無視、停止、コアダンプなどである。
スレッドは
これを深く理解するために複数スレッドのプロセスのメモリ配置を見てみる。 プロセスのメモリ配置は以下のようになっている。
メモリアドレス | 領域名 | 説明 |
---|---|---|
0x00000000~0x3fffffff | Kernel | OSがプロセスを管理するための領域, TCBやPCBなどもここ。 |
0x40000000~0x7fffffff | コード | プログラムのコード |
0x80000000~0xbfffffff | ヒープ | プログラム実行中に動的に確保されるメモリ. static変数もここ。 |
0xc0000000~0xfbffffff | スタック | 0xc00000~0xc0ffffはスレッド1用 |
0xc10000~0xc1ffffはスレッド2用 | ||
0xc20000~0xc2ffffはスレッド2用 | ||
0xc30000~0xfbffffffは新しいスレッド用 | ||
0xfc000000~0xffffffff | IO | ペリフェラルIO(メモリマップドIO)レジスタ |
ここからすぐにわかることだが、スレッドは他のスレッドのスタック領域に(危ないが)アクセスできるし、IO領域にもアクセスできる。 もちろんスレッド毎に異なる値を持つ変数にアクセスすることができる。スレッド毎に異なる値をスレッドローカルな変数と呼ぶ。
なお、通常は共通のデータはヒープ領域に配置することになる。 これいがいもマナーが悪いがグローバル変数を使用する場合もある。
次はグローバル変数を使用する例である。
次はヒープ領域に入れてグローバルで渡す例である。
次はデータをポインタとして渡す方法である。