地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

カーネルスレッドの生成順

カーネルスレッド生成

kernel_thread()

カーネルスレッドを生成する入口。引数にスレッドの用の値を渡している?なのでプロセスというよりスレッドを生成する。

kernel_thread()で何している

  • do_fork()
    • task_strcutのコピーを作り実行可能プロセスのリストに登録する。プロセスディスクリプタからポインタしている各資源は親と共有している。
    • EAX、SP、IPは子プロセス独自のもの。
    • IPはkernel_thread_helperを設定
      • カーネルスレッド関数をcallするやつ。カーネルスレッドの処理が終わったらここに戻りdo_exitする。

カーネルスレッド生成する際はexecはしていないのでユーザーモードにならずカーネルスレッドとして生成される。親と各資源を共有してスタックやIPなどは別の箇所を指しているスレッド。

kernel_init()について

  • kernel_thread()で生成されたカーネルスレッド。
  • initramfsを使っている場合はramfsの/initを起動させる。

/init

  • kernel_init()の中でinitramfsの/initを実行する。
  • 親がカーネルスレッドだが特別でユーザプロセスに変身する

/initがユーザプロセスとして生成されるまでの流れ

  • run_init_process()
    • kernel_init()が呼び出す。このとき大概はinitramfs使用しているので引数には/init
  • kernel_execve()
    • sys_execve()を呼び出す。
  • sys_execve()
    • exec系システムコールの入り口にもなっている。
    • 実行ファイルをメモリにマッピング
    • カーネルスレッド(kernel_init)から/initプロセスを生成するときにはカーネルスタックのカーネルモードの値をユーザーモードの値に上書きしてユーザープロセスに変身させるみたい
       + ユーザーモードを表す__USER_CS, __USER_DSの値が使用されている。
       + なのでこのsys_execveを使うとユーザーモードのプロセスが生成される。
       + /initプロセス生成はこれを利用して親がカーネルモードプロセスだがユーザーモードプロセスになる
      

スタックの上書き

  • EIP 動的リンカの開始ポイント(共有ライブラリをリンクしているので)
  • ESP ユーザーモードのスタックポインタ
  • DS __USER_DS
  • ES __USER_DS
  • SS __USER_DS
  • CS __USER_CS

システムコールの割り込み処理から戻るときにCPUがカーネルモードからユーザモードに移行したことを感知する。(CSが変化したのを感知する)なので、最初にシステムコールした時にはEFLAGS、CS、EIPしか積まないが、システムコールから復帰するときに特権の移行が発生するのでユザーモードに上書きされたSS,ESPもpopされる。よってユーザーモードになる。

  • CPUがシステムコールの時に自動でスタックにpush/pop
    • 特権移行なし
      • EFLAGS、CS、EIP
    • 特権移行あり
      • SS、ESP、EFLAGS、CS、EIP