第17回カーネル読書会 2001年10月17日 高杉@YLUG YLUG読書会 takasugi@yokohama.email.ne.jp
読書会の目次 1.シグナルと割込み 2.シグナル 3.割込み (1)ハードウェア割込み ・ボトムハーフ (2)ソフトウェア割込み ・ボトムハーフ (2)ソフトウェア割込み ・システムコール (3)フォールト YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルと割込みを読む ・詳解Linuxカーネル:監訳者ことば 本気でLinuxカーネルを理解しようと考えた場合は、 PCハードウェアの低レベルな機能の理解が必要。 ・詳解Linuxカーネル:はじめに カーネルを完全に理解するには、ハードウェアを 制御するアセンブリ言語を少し学ぶ必要がある。 YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルと割込みの勉強 アセンブラの理解が必要 (アセンブラルーチンが多い) kernel勉強に最適! ハードウェアの理解が必要 ただ、とても難しい ハードウェアの理解が必要 (ハードウェアの動作が見える) コンパイラ連携の理解が必要 (スタックやfixupの連携) YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルと割込みの差 ユーザモード ・プロセスの処理中 カーネルモード ・カーネルの処理中 シグナル ハードウェアモード ・デバイスの動き YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルとは シグナルは、Unix システムで使用される最も古いプロセス間通信の方法である。シグナルは、ひとつ以上のプロセスに対して非同期イベント(asynchronous events)を伝達するために使用される。シグナルが生成されるのは、キーボード割り込みがあったり、プロセスが仮想メモリ内に存在しない場所にアクセスしようとしてエラーが起きたときなどである。シグナルは、シェルが子プロセスに対してジョブ制御の信号を伝達するときにも利用される。 http://www.linux.or.jp/JF/JFdocs/The-Linux-Kernel-6.html YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルの遷移 signal sigaction RT-signal sigvec BSD 伝統的なSignal 同一シグナルが発生すると対応できない問題があった。 現在のSignal 同一シグナルが発生するとブロックができる。ただ、1つしか保留できない。 次期のSignal? 同一シグナルが発生した場合、 1つ以上の保留できる。 YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルの一覧 P282 表9-1 番号 シグナル名 コメント 1 SIGHUP 端末やプロセスのハングアップ 2 SIGINT キーボードからの割込み 3 SIGQUIT キーボードからの終了 4 SIGILL 不正な命令の実行 5 SIGTRAP デバック用のブレークポイント 6 SIGABRT 異常終了 7 SIGBUS バスエラー : 31 SIGUNUSED 未使用(Linux2.4ではSIGSYS) YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルの送信 P290 9.2 struct sigpending send_sig_infoや send_sigで変更する。 signal_struct *sig : sigpending pending sigqueue head sigqueue tail sigset_t signal siginfo_t siginfo_t send_sig_infoや send_sigで変更する。 force_sig_infoや force_sigも良く似たもの。 struct task_struct YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルの受信 P152 図4-5 syscall出口 割込出口 例外出口 task_struct 起動するプロセス決定 sigpending そのプロセスにシグナル有り? シグナル起動 YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルの起動 P298 図9-1 do_signal() handle_signal() setup_frame() return sys_sigreturn() restore_sigcontext() コンテキスト退避& frame操作 シグナルハンドラ sigreturn コンテキスト回復& frame操作 YLUG読書会 takasugi@yokohama.email.ne.jp
フレームの操作 P300 図9-2 foo() kernel handler() 成長 バッファオーバフローと原理は同じ fooスタック コンテキストの退避とごまかし foo()とhandler()の間のスタックにコンテキストを退避し、返りアドレスはごまかす。 handlerスタック 成長 バッファオーバフローと原理は同じ YLUG読書会 takasugi@yokohama.email.ne.jp
シグナルセーフ P284 枠外 main() handler() foo() foo() foo() foo() ハンドラ外部と内部で共用領域を更新してはいけない (カウンタの更新やポインタの張替えなど) YLUG読書会 takasugi@yokohama.email.ne.jp
割込みの種類 種類 Intelドキュメント 割込み マスカブル・ノンマスカブル 例外 フォルト 割込み命令から再実行 トラップ P117 4.2 種類 Intelドキュメント 割込み マスカブル・ノンマスカブル 周辺機器からの信号 例外 フォルト 割込み命令から再実行 保護機能、MMUにより発生 トラップ 次命令から実行 ソフトウェア割込みにより発生 アボート 致命的エラー YLUG読書会 takasugi@yokohama.email.ne.jp
割込みの一覧 P123 P137 番号 割込み コメント 0 除算エラー devide_error() 1 デバック例外 debug() 2 未使用 nmi() : Intelが予約している(18から31まで) 32 タイマ IRQは0 33 キーボード IRQは1 34 カスケード IRQは2 255 YLUG読書会 takasugi@yokohama.email.ne.jp
割込みの処理 P125 4.2.5 1.割込み元が割込み先へ移動できるかチェック。 2.割込み元が割込みを発生できるかチェック。 3.特権レベルが変更されていたら、スタックの用意が必要。 TRレジスタからTSSを求めて、SSとESPを退避する。 4.スタックにEFLAGSとCSとEIPを退避する。 5.IDTのセレクタとオフセットをCSとEIPにロードする。 YLUG読書会 takasugi@yokohama.email.ne.jp
割込みの動作 P125 4.2.5 GDTR BASE LIMIT IDTR BASE LIMIT IDT 割込みハンドラ CSレジスタ BASE LIMIT Kernel code, User code, : TSS,LDT TSS.LDT CPL IDT SEG SEL DPL OFFSET 256 割込みハンドラ セグメント機構 YLUG読書会 takasugi@yokohama.email.ne.jp
割込みでは、Taskは変更されず、特権レベルが変更される。 割込みのスタック P53 2.3 P95 3.2.2 割込みでは、Taskは変更されず、特権レベルが変更される。 GDTR BASE LIMIT TSS Kernel code, User code, : TSS,LDT TSS.LDT Type:B DPL BASE ADDR TR セレクタ値 task_struct tss_struct NR_tasks セグメント機構 YLUG読書会 takasugi@yokohama.email.ne.jp
割込みからシグナルへ P176 5.5.3 P244 7.4 IDT task_struct sigpending 割込みハンドラ CSレジスタ IDT CPL task_struct SEG SEL DPL OFFSET sigpending 割込みハンドラ シグナル登録 ボトムハーフ セグメント機構 シグナル起動 YLUG読書会 takasugi@yokohama.email.ne.jp
スタックのイメージ図 P81 3.1 Kernel stack Type:B DPL BASE ADDR task_struct Kernel code, User code, : TSS,LDT TSS.LDT Kernel stack esp Type:B DPL BASE ADDR task_struct signal_struct tss_struct セグメント機構 TR User stack YLUG読書会 takasugi@yokohama.email.ne.jp
割込みの具体例 CPU IRQ割込み システムコール フォールト YLUG読書会 takasugi@yokohama.email.ne.jp
IRQハンドラ P138 図4-4 P143 4.6.4 status hw_interrupt_type action depth do_IRQ 0 1 i 63 PIC回路を操作する超低レベルIOルーチン (8259Aなど) irq_desc_t status hw_interrupt_type action depth irqaction irqaction irqaction IRQ全体を抑止するのは、CPUに命令を発行 個別IRQを抑止するのは、PIC回路に命令を発行 Irq共用 YLUG読書会 takasugi@yokohama.email.ne.jp
ボトムハーフの種類 P145 4.6.6 P146 表4-3 番号 コメント CONSOLE_BH 仮想コンソール IMMEDIATE_BH 即時実行タスクキュー KEYBOARD_BH キーボード SCSI_BH SCSIインタフェース SERIAL_BH シリアルポート TIMER_BH タイマ TQUEUE_BH タイマ実行キュー ボトムハーフは割り込みに対応した処理を行うが、優先度の低い関数である。 カーネルが適当なタイミングで呼び出されるのを待っている。 YLUG読書会 takasugi@yokohama.email.ne.jp
ボトムハーフの仕組み P147 4.6.6 割込み処理の遅延実行 TIMER_BH CONSOLE_BH : IMMEDIATE_BH update_times() run_old_timers() run_timer_list() } bh_base TIMER_BH CONSOLE_BH : IMMEDIATE_BH TQUEUE_BH tqueue_bh(){ run_task_queue(&tq_**) } do_bottom_half() tqueue_struct { 呼び出す関数など } tqueue_struct { 呼び出す関数など } tqueue_struct { 呼び出す関数など } 割込み処理の遅延実行 YLUG読書会 takasugi@yokohama.email.ne.jp
動作のタイミング P152 図4-5 割込出口 例外出口 syscall出口 リターン ボトムハーフ実行 ボトムハーフ実行 元はカーネル? 再スケジュール? シグナル実行 リターン YLUG読書会 takasugi@yokohama.email.ne.jp
優先度のイメージ 高 割込み処理 ボトムハーフ カーネルモード処理 優先度 シグナル処理 ユーザモード処理 低 YLUG読書会 takasugi@yokohama.email.ne.jp
SMPでの割込み P360 11.4.4 P352 図11-2 do_irq実行 do_irq実行 CPU 0 (ローカルAPIC) Lockで制御しながら 切替実行(interleave) do_irq実行 do_irq実行 CPU 0 (ローカルAPIC) CPU 1 (ローカルAPIC) ICCバス I/O APIC YLUG読書会 takasugi@yokohama.email.ne.jp
SMPでのボトムハーフ P364 11.4.5 BH実行中 CPU 0 (ローカルAPIC) CPU 1 (ローカルAPIC) ICCバス ・誰かボトムハーフを実行している。 ・ボトムハーフが禁止されてる。 ・誰か割込みハンドラを実行している。 ・割込みが禁止されている。 BH実行中 CPU 0 (ローカルAPIC) CPU 1 (ローカルAPIC) ICCバス I/O APIC YLUG読書会 takasugi@yokohama.email.ne.jp
システムコール P266 図8-1 ユーザモード カーネルモード main malloc sys_call do_mmap malloc() 割り込みゲートで特権レベル・スタック・コードが変更される ユーザモード カーネルモード main malloc sys_call do_mmap malloc() mmap() do_mmap return return return ret_from_syscall() このタイミングでボトムハーフやシグナルが起動される YLUG読書会 takasugi@yokohama.email.ne.jp
引数へアクセス P272 8.2.5 P75 2.5.5 CR3 カーネルからはユーザは見える。 ユーザからカーネルは見れない。 ページディレクトリテーブル 物理0x00100000 論理0xc0000000 ページテーブル ページ CR3 カーネル swapper_pg_dir U/SビットOFF U/SビットON 物理0x???00000 論理0x00000000 4Kバイト 1024個のPTE ユーザ カーネルからはユーザは見える。 ユーザからカーネルは見れない。 YLUG読書会 takasugi@yokohama.email.ne.jp
例外とfixupコード P274 8.2.6 P679 B.2 do_page_faule() 割込処理 カーネル fixupルーチン do_page_faule() get_user search_exeption_table() フォルトしたアドレスから リカバするための命令を 検索して、JMPする。 ユーザ _ex_table フォルトするかもしれない命令アドレス リカバするための命令アドレス フォルトするかもしれない命令アドレス リカバするための命令アドレス フォルトするかもしれない命令アドレス リカバするための命令アドレス YLUG読書会 takasugi@yokohama.email.ne.jp
システムコールの再実行 P302 9.3.4 eipを2バイト戻して、引数(レジスタ)を整え、リタンすると再実行 do_signal() handle_signal() setup_frame() return sys_sigreturn() restore_sigcontext() コンテキスト退避& frame操作 シグナルハンドラ sigreturn コンテキスト回復& frame操作 eipを2バイト戻して、引数(レジスタ)を整え、リタンすると再実行 YLUG読書会 takasugi@yokohama.email.ne.jp
ページフォルト P245 図7.5 0x0e do_page_fault() CR2 faultしたアドレス 割 込 Kernelか? No Yes find_vma 不正syscall コピーオンライト デマンド ページング SIGSEGV Oops fixup処理 7.4.4 7.4.3 7.4.1(9.2) 3.4.1 8.2.6 YLUG読書会 takasugi@yokohama.email.ne.jp
今後の課題 ●2.4系カーネルで拡張された機能 TSSが2.2系はプロセス毎、2.4系はCPU毎 softirqとtaskletについて ●カーネル内の他制御 メモリ管理やファイルシステムなど YLUG読書会 takasugi@yokohama.email.ne.jp
参考文献 ●詳解Linuxカーネル O’REILLY Japan DANIEL P.BOVET MARCO CESATI著 高橋 浩和 早川 仁 監訳 ●Pentiumファミリーディベロッパーズマニュアル ●はじめて読む486 ASCII 蒲地 輝尚 著 YLUG読書会 takasugi@yokohama.email.ne.jp