スキップしてメイン コンテンツへ

 none
「ntoskrnl.exe」について RRS feed

  • 質問

  • 以下、Windowsの基本動作の一般知識としての質問です。学習に適した書物やインターネット情報へのポインタへのご教示でも大歓迎です。

    いわゆる「カーネル」ないし「カーネル・エグゼクティブ」と呼ばれる「ntoskrnl.exe」についてです。ブードが完了してWindowsが定常的に稼働している状態では、ntoskrnl.exeは独自のプロセスとしては存在していないのでしょうか? それともプロセスとして存在しているのでしょうか?

    メモリ上にコードが常駐していることは理解していますが、
    ―コードの実行はなんらかのNative APIのコールに依る、プロセスの起源はユーザーモードのプログラムで、APIコール時にカーネルモードに切り替わる、と理解すべきか、
    ―コードは独自のプロセスとしてカーネルモードで常に実行されており、Native APIのコールは一種のプロセス間通信である、と理解すべきか、
    どちらなのでしょうか?

    タスクマネージャで見ることのできる、Process ID=4の「System」というプロセスは、本件と関連がありますでしょうか?



    • 編集済み 外池 2016年7月24日 8:05
    2016年7月24日 8:00

回答

  • ntoskrnl.exe はその名前のとおり NT カーネルであり、Windows システムでの「核」となるモジュールです。
    このモジュール内には、I/O マネージャ、キャッシュ マネージャ、メモリ マネージャといった各種マネージャと、Native API の実態が実装されています。

    アプリやサービス等のユーザー モードから Native API をコールした場合、その Interface は ntdll.dll 内の対応するエントリ ポイントになり、実際の処理は ntdll.dll が sysenter で呼び出すカーネルモード側の、ntoskrnl.exe 内の対応する関数で行われることになりますが、それが "System Process" 内のスレッドで行われる訳ではありません。
    (ちなみに ntoskrnl.exe 内の対応する関数は、そのリクエストに対応するドライバ群を呼び出すことになります。)

    > ntoskrnl.exeは独自のプロセスとしては存在していないのでしょうか?
    > それともプロセスとして存在しているのでしょうか?

    Task Manager の Image Path Name に "ntoskrnl.exe" と表示される "System Process" は、OS の起動直後からシャットダウン直前までの間、終了することなく常に存在します。
    (もし仮に "System Process" が予期せずに終了した場合は BSOD になるんだと思いますが、私はそのような状況に出くわしたことはありませんし、そのようなダンプも見たことがありません。)
    Windows 上で起動中のすべてのプロセスは EPROCESS オブジェクトとして表されますが、"System Process" に対応する EPROCESS オブジェクトも確実に存在します。
    ------------------------------------------------------------------------------------
    1: kd> !process 0 0
    **** NT ACTIVE PROCESS DUMP ****
    PROCESS ffffe000324658c0
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001aa000  ObjectTable: ffffc0019fc03000  HandleCount: <Data Not Accessible>
        Image: System

    PROCESS ffffe0003389c040
        SessionId: none  Cid: 0128    Peb: 7ff60c41f000  ParentCid: 0004
        DirBase: 0541b000  ObjectTable: ffffc001a01b0ac0  HandleCount: <Data Not Accessible>
        Image: smss.exe
    ....
    ....
    PROCESS ffffe00033fea8c0
        SessionId: 0  Cid: 0258    Peb: 7ff70505f000  ParentCid: 01e8
        DirBase: 1cbea000  ObjectTable: ffffc001a144ed80  HandleCount: <Data Not Accessible>
        Image: svchost.exe
    ....
    ------------------------------------------------------------------------------------

    すでに佐祐理さんも指摘されているように、"System Process" はユーザ モード空間が存在しない「特別な」プロセスになります。
    ただ、一般的に EPROCESS 構造体の ImageFileName メンバーにはそのプロセスに対応する実行ファイル名がセットされますが、"System Process" の場合このフィールドには "ntoskrnl.exe" ではなく、"System" という文字列がセットされています。
    (なお EPROCESS 構造体の InheritedFromUniqueProcessId  メンバにはmそのプロセスを起動させた「親プロセス」の PID が保持されますが、"System Process" の場合このフィールドは NULL になります。)

    > ―これら以外にも、カーネルモードの世界のみを見ても、ブートに起源をもつプロセスと、
    > そこでやりくりされるスレッドがあるんだろうな、とも思っています。
    > ー両者を区別して理解すべきか、区別に意味が無いのか、が知りたいポイント。

    いまいち「知りたいポイント」がよくわからないのですが、「一般のアプリやサービス等のプロセスと "System Process" を区別するべきか? 」ということであれば、区別するべきであると考えます。
    ですが、カーネル モード側の処理だから "System Process" 内で処理される。。。というわけではありません。

    任意の(アプリ or サービス)プロセスから発生するカーネル モード側の処理うち、そのほとんどは「その」プロセス空間内で処理されます。
    下記は、64 ビット OS において 32 ビット プロセスである Skype.exe が CreateFile() API コールにて、"C:\Users\xxxxx\AppData\Local\Microsoft\Windows\INetCookies\6WGHZY5P.txt" ファイルのオープン リクエストを発行し、NTFS ファイル システム ドライバの対応するエントリ ポイントが呼ばれたタイミングでのコール スタックを示しています。

    ------------------------------------------------------------------------------------
    ;; 64 ビット側 Skype.exe プロセスのスレッド
    0: kd> !thread
    THREAD ffffe00034c97880  Cid 09ec.0b84  Teb: 000000007fe83000 Win32Thread: fffff90140978b50 RUNNING on processor 0
    IRP List:
        ffffe00032c4c820: (0006,0430) Flags: 00000884  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001a56da520
    Owning Process            ffffe00032cb1080       Image:         Skype.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      20800734       Ticks: 1 (0:00:00:00.015)
    Context Switch Count      399            IdealProcessor: 1            
    UserTime                  00:00:00.062
    KernelTime                00:00:00.078
    Win32 Start Address ntdll_77520000!TppWorkerThread (0x0000000077534930)
    Stack Init ffffd001b9486dd0 Current ffffd001b9486540
    Base ffffd001b9487000 Limit ffffd001b9481000 Call 0
    Priority 9 BasePriority 8 UnusualBoost 1 ForegroundBoost 0 IoPriority 2 PagePriority 5
    Child-SP          RetAddr           : Args to Child                                                           : Call Site
    ffffd001`b94864b8 fffff801`3ce7db1e : 00000000`00000000 00000000`00000000 00000000`00000270 ffffe000`345d5380 : Ntfs!NtfsFsdCreate
    ffffd001`b94864c0 fffff801`3cea6349 : ffffd001`b94865a0 ffffe000`32acd400 ffffe000`32c4c820 ffffe000`335afdb0 : fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x2ce
    ffffd001`b9486560 fffff802`96fd7361 : 00000000`00000000 00000000`00000085 00000000`00000000 00000000`00000000 : fltmgr!FltpCreate+0x339
    ffffd001`b9486610 fffff802`970bdefe : 00000000`00000000 00000000`00000000 ffffc001`9fe57a40 ffffe000`3356ec70 : nt!IopParseDevice+0x6c1
    ffffd001`b9486830 fffff802`96fdb9c3 : 00000000`00000000 ffffd001`b94869e8 00000000`00000040 ffffe000`32498f20 : nt!ObpLookupObjectName+0x7be
    ffffd001`b9486970 fffff802`97044dfb : 000100bc`00000001 ffffe000`34754398 00000000`00000001 00000000`00000020 : nt!ObOpenObjectByName+0x1e3
    ffffd001`b9486aa0 fffff802`97044a84 : 00000000`073ce818 ffffe000`80100080 00000000`073cf0d0 ffffe000`32cb1080 : nt!IopCreateFile+0x36b
    ffffd001`b9486b40 fffff802`96d78ab3 : ffffe000`34c97880 ffffd001`b9486cc0 ffffd001`b9486be8 fffff802`00000001 : nt!NtCreateFile+0x78
    ffffd001`b9486bd0 00007fff`b1700c0a : 00000000`77459c68 00000000`074cf9a4 00000000`00000000 00000000`074cf998 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`b9486c40)
    00000000`073ce7a8 00000000`77459c68 : 00000000`074cf9a4 00000000`00000000 00000000`074cf998 00000000`7fe83000 : ntdll!NtCreateFile+0xa
    00000000`073ce7b0 00000000`7745a44b : 00000000`074cf998 00000000`00000000 00000000`00000000 00000000`00000064 : wow64!whNtCreateFile+0xf8
    00000000`073ce880 00000000`77511dc5 : 00000023`7755d05c 00000000`00000023 00000000`00000001 00000000`76708cc0 : wow64!Wow64SystemServiceEx+0xfb
    00000000`073cf130 00000000`7746219a : 00000000`00000000 00000000`77511574 00000000`00000000 00000000`77462380 : wow64cpu!ServiceNoTurbo+0xb
    00000000`073cf1e0 00000000`774620d2 : 00000000`00000000 00000000`00000000 00000000`073cfd30 00000000`073cf830 : wow64!RunCpuSimulation+0xa
    00000000`073cf230 00007fff`b1688dab : 00000000`00000000 00000000`77461f60 00000000`00000000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x172
    00000000`073cf770 00007fff`b1688c8e : 00000000`073cf830 00000000`00000000 00000000`7ffdf000 00000000`00000000 : ntdll!_LdrpInitialize+0xcb
    00000000`073cf7e0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

    0: kd> dt nt!_IRP ffffe00032c4c820 Tail.Overlay.C*
       +0x078 Tail           :
          +0x000 Overlay        :
             +0x040 CurrentStackLocation : 0xffffe000`32c4cbc0 _IO_STACK_LOCATION
    0: kd> dt nt!_IO_STACK_LOCATION 0xffffe000`32c4cbc0
       +0x000 MajorFunction    : 0 ''
       +0x001 MinorFunction    : 0 ''
       +0x002 Flags            : 0 ''
       +0x003 Control          : 0xe0 ''
       +0x008 Parameters       : <unnamed-tag>
       +0x028 DeviceObject     : 0xffffe000`335f1030 _DEVICE_OBJECT
       +0x030 FileObject       : 0xffffe000`345d5380 _FILE_OBJECT
       +0x038 CompletionRoutine : 0xfffff801`3ce7f480     long  fltmgr!FltpSynchronizedOperationCompletion+0
       +0x040 Context          : 0xffffe000`32acd400 Void
    0: kd> !fileobj 0xffffe000`345d5380
    \Users\xxxxx\AppData\Local\Microsoft\Windows\INetCookies\6WGHZY5P.txt
    Device Object: 0xffffe0003356eca0   \Driver\volmgr
    Vpb is NULL
    Flags:  0x22
     Synchronous IO
     Sequential Only

    CurrentByteOffset: 0

    ;; 32 ビット側 Skype.exe プロセスのスレッド
    0: kd:x86> kvn
     # ChildEBP          RetAddr           Args to Child                                        
    00 074cf93c 766f5837 074cf988 80100080 074cf9c0 ntdll_77520000!NtCreateFile+0xc (FPO: [11,0,0])
    01 074cfa08 766f5552 00000001 00000003 074cfa20 KERNELBASE!CreateFileInternal+0x2da (FPO: [4,35,4])
    02 074cfa3c 71ac4747 12151430 80000000 00000001 KERNELBASE!CreateFileW+0x5e (FPO: [7,6,0])
    03 074cfac4 71ac451e 00000000 00000000 074cfb10 wininet!RetrieveUrlCacheEntryStreamHelper+0x1a0 (FPO: [Non-Fpo])
    04 074cfb14 71b424c8 00000000 00000000 00000000 wininet!UrlCacheRetrieve+0xfa (FPO: [Non-Fpo])
    05 074cfb80 71b4247a 076ec650 71afbed3 10ab5ba8 wininet!CCookieLocation::ReadCacheFile+0x47 (FPO: [Non-Fpo])
    06 074cfb88 71afbed3 10ab5ba8 00000000 11282fd8 wininet!CCookieLocation::ReadCacheFileIfNeeded+0x1c (FPO: [0,1,0])
    07 074cfbfc 71ac74ae 074cfc1c 10ab5ba8 11282fd8 wininet!HTTP_REQUEST_HANDLE_OBJECT::CreateCookieHeaderIfNeeded+0x231 (FPO: [Non-Fpo])
    08 074cfc44 71ac4ff8 11282fd8 71ac5020 074cfc68 wininet!HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_Start+0x41c (FPO: [1,11,4])
    09 074cfc5c 71ac4dc1 11282fd8 10ab5ba8 081ca040 wininet!CFsm_HttpSendRequest::RunSM+0x77 (FPO: [Non-Fpo])
    0a 074cfcb0 71acd160 081ca040 074cfce8 074cfd5c wininet!CFsm::Run+0x161 (FPO: [Non-Fpo])
    0b 074cfd8c 71acd511 bacfc17e 037b75d0 71acd4f0 wininet!CFsm::RunWorkItem+0x234 (FPO: [Non-Fpo])
    0c 074cfdc0 7753419c 074cfe2c 11282fd8 037b75d0 wininet!FailFastThreadPoolCallback<&CFsm::RunWorkItemWrapper>+0x21 (FPO: [SEH])
    0d 074cfde8 775417a8 074cfe2c 0766ebb8 bc65d1cc ntdll_77520000!TppSimplepExecuteCallback+0x6c (FPO: [Non-Fpo])
    0e 074cff80 77257c04 037b75d0 77257be0 bc339ed2 ntdll_77520000!TppWorkerThread+0x4f3 (FPO: [SEH])
    0f 074cff94 7757ab8f 037b75d0 bc65d190 00000000 KERNEL32!BaseThreadInitThunk+0x24 (FPO: [Non-Fpo])
    10 074cffdc 7757ab5a ffffffff 7755ffe8 00000000 ntdll_77520000!__RtlUserThreadStart+0x2f (FPO: [SEH])
    11 074cffec 00000000 77534930 037b75d0 00000000 ntdll_77520000!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

    0: kd:x86> du 12151430
    00000000`12151430  "C:\Users\xxxxx\AppData\Local\Mic"
    00000000`12151470  "rosoft\Windows\INetCookies\6WGHZ"
    00000000`121514b0  "Y5P.txt"
    ------------------------------------------------------------------------------------

    上記コール スタックを見ていただければわかると思いますが、Skype.exe の 32 ビット プロセス側から発行された KERNELBASE!CreateFileW コールは、Native API コールである ntdll_77520000!NtCreateFile コールに変換されたあと、Skype.exe の 64 ビット プロセス側の ntdll!NtCreateFile に渡されています。
    その後 sysenter によりカーネル モード側の nt!NtCreateFile ルーチン (ntoskrnl.exe 内) を経由して NTFS ドライバにファイル オープン リクエストが渡されていますが、この一連の処理はすべて Skype.exe プロセス内で行われています。

    Windows では、32 ビット プロセスは 2G Bytes のユーザー モード空間と 2G Bytes のカーネル モード空間の計 4G Bytes の仮想メモリ空間、64 ビット プロセスは 8T Bytes のユーザー モード空間と 248T Bytes のカーネル モード空間の計 256T Bytes の仮想メモリ空間を持ちます。
    つまり "System Process" 以外の一般のプロセスは、ユーザー モード空間とカーネル モード空間の2種類の仮想メモリ空間を持ち、同一プロセス空間内で必要に応じてユーザ モード空間とカーネル モード空間を行き来している訳です。
    ここら辺の詳細については、下記 MSDN サイト情報が参考になると思います。

    ------------------------------------------------------------------------------------
    仮想アドレス領域
    https://msdn.microsoft.com/ja-jp/library/windows/hardware/hh439648(v=vs.85).aspx
    ------------------------------------------------------------------------------------

    ただし、例外的にユーザ プロセスから発生した処理の一部が "System Process" 内で処理される可能性はあります。
    これはユーザ プロセス側から意図的にそうさせるのではなく、その処理に介在するドライバの実装に起因して発生します。
    デバイス ドライバやファイル システム ドライバ、あるいは何かのフィルタ ドライバ等のカーネル モード側で動作するドライバは、"System Process" 内で動作する System Worker Thread を利用することができます。
    カーネル モード側で動作するドライバは可能な限り素早く処理することが求められるため、時間のかかる処理や同一コンテキストで行う必要のない処理を、Work Item として System Woker Queue にポストし、"System Process" 内の System Worker Thread で実行させることができます。
    (この System Woker Queue にポストされた Work Item は、オリジナルのスレッド コンテキストは全く別の System Worker Thread で実行されます。)

    > カーネルモードのメモリ空間は単一でカーネルモードの
    > スレッドすべてで共有されていると理解しています。
    > その観点で、1つのプロセスと理解して差支えないわけですよね。
    > ただ、特定のユーザーモードプロセス・スレッドを起源にもつ
    > カーネルモードスレッドは、起源をちゃんと覚えている、
    > 自身の処理が終われば、元のユーザーモードプロセス・スレッドに
    > 制御を戻せる、わけですよね。
    > 現時点で、描いている姿はこんな感じです。

    カーネル モード空間は、すべてのプロセス間で共有されますが、だからと言ってカーネル モード空間が1つのプロセスであるという認識は、間違いだと思います。
    先にも示したように、アプリやサービス等の一般のプロセスにも、カーネル モード空間は存在しています。
    "System Process" がユーザ モード空間を持たないのは、単に持つ必要がないだけだと思います。
    言い換えれば、"System Process" はユーザ プロセスの様に、特定の機能に特化した処理を行うのではなく、様々なプロセスから付随して発生するシステムが管理すべき処理を行うために、独立したプロセスとしてい存在している。。。ということなんだと思います。
    例えば、さまざまなプロセスから発生するメモリの割り当て/解放処理では、その処理を任意のプロセス コンテキスト内だけで実現させることは不可能です (物理メモリの空き領域が不足している場合、そのプロセス内だけで物理メモリの使用状況を調整することは不可能です) し、各種周辺デバイスから発生するハードウェア割り込みを任意のユーザ プロセスで処理させたら、おそらくおかしなことになってしまうと思います。
    "System Process" はその名のとおり、システムが管理すべき処理を実行するためのプロセスであり、基本的にそのような処理は任意のアプリケーション (やサービス) から明示的にリクエストされるような性質のものではないため、ユーザ モード空間を持たない。。。ということなんだと思います。

    > Unix系だと「カーネルモードのプロセスは存在する」と説明されていて、
    > システムコールに際しては「on behalf of」ユーザープロセスとして
    > カーネルモードのスレッドを実行する、ということらしい・・・。
    > Windowsもこれと同じことか? というのが別の視点での知りたいポイントです。

    Unix 系のことはよくわかりませんが、Windows での "System Process" は確かにカーネル モード空間しか持たないプロセスですが、すべてのカーネル モード空間側の処理を行うプロセスではありません。
    任意のプロセス内で処理できるもの、あるいはそのスレッド コンテキストで処理すべきものについては、そのプロセス内の「カーネル モード空間」で処理されます。
    これは、"System Process" とは全く別次元の話です。

    すでに佐祐理さんも提案されますが、この手の詳細を知りたいのであれば、「インサイド Windows」 (原題 "Windows Internals") を読まれることをお勧めします。
    ただ (私だけが感じてることかもしれませんが) この本はとても難しいので、WinDBG 等のカーネル デバッガを使用して、実際の PC の挙動のを確認しながら読み進めるのが、一番効率的だと思います。
    (実際、この本の中でも WinDBG を使用した例が、多数掲載さています。)

    蛇足ですが。。。
    「インサイド Windows 第4版」の監修をされた豊田孝さんが、昔このフォーラムに参加されていました。
    今は御覧になっているかはわかりませんが。。。

    • 回答の候補に設定 星 睦美 2016年7月26日 5:53
    • 回答としてマーク 星 睦美 2016年7月29日 7:57
    2016年7月25日 8:17
  • カーネルはカーネル空間のみで動作し、ユーザー空間を持ちません。またカーネル空間内はユーザー空間のようにプロセス分離されていません。ただしカーネルスレッドはユーザースレッドとは別に存在するため、そのスレッドが便宜上所属しているのがSystemプロセス(PID=4)です。もちろん特定のプロセスに結び付いたカーネルスレッドであれば該当プロセスに所属しますが。

    いちおうタスクマネージャでImage path nameを表示させるとSystemプロセスはntoskrnl.exeとはなっています。が、ユーザー空間ではなくカーネル空間へ読み込まれているので、これも便宜上の表示でしかないかと。

    というような説明を書いてみたものの断片的な説明しかできず、それはWebでも同じかと思います。書籍として系統立てて整理されたものを読まれた方がいいと思います。とりあえずインサイドWindows 第6版 をお勧めします。

    • 回答の候補に設定 星 睦美 2016年7月25日 2:45
    • 回答としてマーク 星 睦美 2016年7月29日 7:56
    2016年7月24日 11:26

すべての返信

  • カーネルはカーネル空間のみで動作し、ユーザー空間を持ちません。またカーネル空間内はユーザー空間のようにプロセス分離されていません。ただしカーネルスレッドはユーザースレッドとは別に存在するため、そのスレッドが便宜上所属しているのがSystemプロセス(PID=4)です。もちろん特定のプロセスに結び付いたカーネルスレッドであれば該当プロセスに所属しますが。

    いちおうタスクマネージャでImage path nameを表示させるとSystemプロセスはntoskrnl.exeとはなっています。が、ユーザー空間ではなくカーネル空間へ読み込まれているので、これも便宜上の表示でしかないかと。

    というような説明を書いてみたものの断片的な説明しかできず、それはWebでも同じかと思います。書籍として系統立てて整理されたものを読まれた方がいいと思います。とりあえずインサイドWindows 第6版 をお勧めします。

    • 回答の候補に設定 星 睦美 2016年7月25日 2:45
    • 回答としてマーク 星 睦美 2016年7月29日 7:56
    2016年7月24日 11:26
  • 佐祐理様、ありがとうございます。

    やはり「インサイドWindows」になりますか。職場で購入することにします。邦書で出版されているものの和訳は上質でしょうか・・・。英語版だと7版が出ているようですね。こちらにするかもしれません。

    もう少し具体的に、知りたいことをまとめておきます。

    ―佐祐理さんの仰る「特定のプロセスに結び付いたカーネルスレッド」について、小生は、ユーザーモードのプロセス・スレッドがWindows APIを呼び出し、Native APIを呼び出し、ここでソフトウェア割り込み(int 0x80)かsysenterによりカーネルモードに切り替わる・・・、このような仕組みのものと理解しています。

    ―これら以外にも、カーネルモードの世界のみを見ても、ブートに起源をもつプロセスと、そこでやりくりされるスレッドがあるんだろうな、とも思っています。

    ー両者を区別して理解すべきか、区別に意味が無いのか、が知りたいポイント。

    カーネルモードのメモリ空間は単一でカーネルモードのスレッドすべてで共有されていると理解しています。その観点で、1つのプロセスと理解して差支えないわけですよね。ただ、特定のユーザーモードプロセス・スレッドを起源にもつカーネルモードスレッドは、起源をちゃんと覚えている、自身の処理が終われば、元のユーザーモードプロセス・スレッドに制御を戻せる、わけですよね。現時点で、描いている姿はこんな感じです。

    Unix系だと「カーネルモードのプロセスは存在する」と説明されていて、システムコールに際しては「on behalf of」ユーザープロセスとしてカーネルモードのスレッドを実行する、ということらしい・・・。Windowsもこれと同じことか? というのが別の視点での知りたいポイントです。

    2016年7月24日 11:58
  • ntoskrnl.exe はその名前のとおり NT カーネルであり、Windows システムでの「核」となるモジュールです。
    このモジュール内には、I/O マネージャ、キャッシュ マネージャ、メモリ マネージャといった各種マネージャと、Native API の実態が実装されています。

    アプリやサービス等のユーザー モードから Native API をコールした場合、その Interface は ntdll.dll 内の対応するエントリ ポイントになり、実際の処理は ntdll.dll が sysenter で呼び出すカーネルモード側の、ntoskrnl.exe 内の対応する関数で行われることになりますが、それが "System Process" 内のスレッドで行われる訳ではありません。
    (ちなみに ntoskrnl.exe 内の対応する関数は、そのリクエストに対応するドライバ群を呼び出すことになります。)

    > ntoskrnl.exeは独自のプロセスとしては存在していないのでしょうか?
    > それともプロセスとして存在しているのでしょうか?

    Task Manager の Image Path Name に "ntoskrnl.exe" と表示される "System Process" は、OS の起動直後からシャットダウン直前までの間、終了することなく常に存在します。
    (もし仮に "System Process" が予期せずに終了した場合は BSOD になるんだと思いますが、私はそのような状況に出くわしたことはありませんし、そのようなダンプも見たことがありません。)
    Windows 上で起動中のすべてのプロセスは EPROCESS オブジェクトとして表されますが、"System Process" に対応する EPROCESS オブジェクトも確実に存在します。
    ------------------------------------------------------------------------------------
    1: kd> !process 0 0
    **** NT ACTIVE PROCESS DUMP ****
    PROCESS ffffe000324658c0
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001aa000  ObjectTable: ffffc0019fc03000  HandleCount: <Data Not Accessible>
        Image: System

    PROCESS ffffe0003389c040
        SessionId: none  Cid: 0128    Peb: 7ff60c41f000  ParentCid: 0004
        DirBase: 0541b000  ObjectTable: ffffc001a01b0ac0  HandleCount: <Data Not Accessible>
        Image: smss.exe
    ....
    ....
    PROCESS ffffe00033fea8c0
        SessionId: 0  Cid: 0258    Peb: 7ff70505f000  ParentCid: 01e8
        DirBase: 1cbea000  ObjectTable: ffffc001a144ed80  HandleCount: <Data Not Accessible>
        Image: svchost.exe
    ....
    ------------------------------------------------------------------------------------

    すでに佐祐理さんも指摘されているように、"System Process" はユーザ モード空間が存在しない「特別な」プロセスになります。
    ただ、一般的に EPROCESS 構造体の ImageFileName メンバーにはそのプロセスに対応する実行ファイル名がセットされますが、"System Process" の場合このフィールドには "ntoskrnl.exe" ではなく、"System" という文字列がセットされています。
    (なお EPROCESS 構造体の InheritedFromUniqueProcessId  メンバにはmそのプロセスを起動させた「親プロセス」の PID が保持されますが、"System Process" の場合このフィールドは NULL になります。)

    > ―これら以外にも、カーネルモードの世界のみを見ても、ブートに起源をもつプロセスと、
    > そこでやりくりされるスレッドがあるんだろうな、とも思っています。
    > ー両者を区別して理解すべきか、区別に意味が無いのか、が知りたいポイント。

    いまいち「知りたいポイント」がよくわからないのですが、「一般のアプリやサービス等のプロセスと "System Process" を区別するべきか? 」ということであれば、区別するべきであると考えます。
    ですが、カーネル モード側の処理だから "System Process" 内で処理される。。。というわけではありません。

    任意の(アプリ or サービス)プロセスから発生するカーネル モード側の処理うち、そのほとんどは「その」プロセス空間内で処理されます。
    下記は、64 ビット OS において 32 ビット プロセスである Skype.exe が CreateFile() API コールにて、"C:\Users\xxxxx\AppData\Local\Microsoft\Windows\INetCookies\6WGHZY5P.txt" ファイルのオープン リクエストを発行し、NTFS ファイル システム ドライバの対応するエントリ ポイントが呼ばれたタイミングでのコール スタックを示しています。

    ------------------------------------------------------------------------------------
    ;; 64 ビット側 Skype.exe プロセスのスレッド
    0: kd> !thread
    THREAD ffffe00034c97880  Cid 09ec.0b84  Teb: 000000007fe83000 Win32Thread: fffff90140978b50 RUNNING on processor 0
    IRP List:
        ffffe00032c4c820: (0006,0430) Flags: 00000884  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001a56da520
    Owning Process            ffffe00032cb1080       Image:         Skype.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      20800734       Ticks: 1 (0:00:00:00.015)
    Context Switch Count      399            IdealProcessor: 1            
    UserTime                  00:00:00.062
    KernelTime                00:00:00.078
    Win32 Start Address ntdll_77520000!TppWorkerThread (0x0000000077534930)
    Stack Init ffffd001b9486dd0 Current ffffd001b9486540
    Base ffffd001b9487000 Limit ffffd001b9481000 Call 0
    Priority 9 BasePriority 8 UnusualBoost 1 ForegroundBoost 0 IoPriority 2 PagePriority 5
    Child-SP          RetAddr           : Args to Child                                                           : Call Site
    ffffd001`b94864b8 fffff801`3ce7db1e : 00000000`00000000 00000000`00000000 00000000`00000270 ffffe000`345d5380 : Ntfs!NtfsFsdCreate
    ffffd001`b94864c0 fffff801`3cea6349 : ffffd001`b94865a0 ffffe000`32acd400 ffffe000`32c4c820 ffffe000`335afdb0 : fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x2ce
    ffffd001`b9486560 fffff802`96fd7361 : 00000000`00000000 00000000`00000085 00000000`00000000 00000000`00000000 : fltmgr!FltpCreate+0x339
    ffffd001`b9486610 fffff802`970bdefe : 00000000`00000000 00000000`00000000 ffffc001`9fe57a40 ffffe000`3356ec70 : nt!IopParseDevice+0x6c1
    ffffd001`b9486830 fffff802`96fdb9c3 : 00000000`00000000 ffffd001`b94869e8 00000000`00000040 ffffe000`32498f20 : nt!ObpLookupObjectName+0x7be
    ffffd001`b9486970 fffff802`97044dfb : 000100bc`00000001 ffffe000`34754398 00000000`00000001 00000000`00000020 : nt!ObOpenObjectByName+0x1e3
    ffffd001`b9486aa0 fffff802`97044a84 : 00000000`073ce818 ffffe000`80100080 00000000`073cf0d0 ffffe000`32cb1080 : nt!IopCreateFile+0x36b
    ffffd001`b9486b40 fffff802`96d78ab3 : ffffe000`34c97880 ffffd001`b9486cc0 ffffd001`b9486be8 fffff802`00000001 : nt!NtCreateFile+0x78
    ffffd001`b9486bd0 00007fff`b1700c0a : 00000000`77459c68 00000000`074cf9a4 00000000`00000000 00000000`074cf998 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`b9486c40)
    00000000`073ce7a8 00000000`77459c68 : 00000000`074cf9a4 00000000`00000000 00000000`074cf998 00000000`7fe83000 : ntdll!NtCreateFile+0xa
    00000000`073ce7b0 00000000`7745a44b : 00000000`074cf998 00000000`00000000 00000000`00000000 00000000`00000064 : wow64!whNtCreateFile+0xf8
    00000000`073ce880 00000000`77511dc5 : 00000023`7755d05c 00000000`00000023 00000000`00000001 00000000`76708cc0 : wow64!Wow64SystemServiceEx+0xfb
    00000000`073cf130 00000000`7746219a : 00000000`00000000 00000000`77511574 00000000`00000000 00000000`77462380 : wow64cpu!ServiceNoTurbo+0xb
    00000000`073cf1e0 00000000`774620d2 : 00000000`00000000 00000000`00000000 00000000`073cfd30 00000000`073cf830 : wow64!RunCpuSimulation+0xa
    00000000`073cf230 00007fff`b1688dab : 00000000`00000000 00000000`77461f60 00000000`00000000 00000000`00000000 : wow64!Wow64LdrpInitialize+0x172
    00000000`073cf770 00007fff`b1688c8e : 00000000`073cf830 00000000`00000000 00000000`7ffdf000 00000000`00000000 : ntdll!_LdrpInitialize+0xcb
    00000000`073cf7e0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0xe

    0: kd> dt nt!_IRP ffffe00032c4c820 Tail.Overlay.C*
       +0x078 Tail           :
          +0x000 Overlay        :
             +0x040 CurrentStackLocation : 0xffffe000`32c4cbc0 _IO_STACK_LOCATION
    0: kd> dt nt!_IO_STACK_LOCATION 0xffffe000`32c4cbc0
       +0x000 MajorFunction    : 0 ''
       +0x001 MinorFunction    : 0 ''
       +0x002 Flags            : 0 ''
       +0x003 Control          : 0xe0 ''
       +0x008 Parameters       : <unnamed-tag>
       +0x028 DeviceObject     : 0xffffe000`335f1030 _DEVICE_OBJECT
       +0x030 FileObject       : 0xffffe000`345d5380 _FILE_OBJECT
       +0x038 CompletionRoutine : 0xfffff801`3ce7f480     long  fltmgr!FltpSynchronizedOperationCompletion+0
       +0x040 Context          : 0xffffe000`32acd400 Void
    0: kd> !fileobj 0xffffe000`345d5380
    \Users\xxxxx\AppData\Local\Microsoft\Windows\INetCookies\6WGHZY5P.txt
    Device Object: 0xffffe0003356eca0   \Driver\volmgr
    Vpb is NULL
    Flags:  0x22
     Synchronous IO
     Sequential Only

    CurrentByteOffset: 0

    ;; 32 ビット側 Skype.exe プロセスのスレッド
    0: kd:x86> kvn
     # ChildEBP          RetAddr           Args to Child                                        
    00 074cf93c 766f5837 074cf988 80100080 074cf9c0 ntdll_77520000!NtCreateFile+0xc (FPO: [11,0,0])
    01 074cfa08 766f5552 00000001 00000003 074cfa20 KERNELBASE!CreateFileInternal+0x2da (FPO: [4,35,4])
    02 074cfa3c 71ac4747 12151430 80000000 00000001 KERNELBASE!CreateFileW+0x5e (FPO: [7,6,0])
    03 074cfac4 71ac451e 00000000 00000000 074cfb10 wininet!RetrieveUrlCacheEntryStreamHelper+0x1a0 (FPO: [Non-Fpo])
    04 074cfb14 71b424c8 00000000 00000000 00000000 wininet!UrlCacheRetrieve+0xfa (FPO: [Non-Fpo])
    05 074cfb80 71b4247a 076ec650 71afbed3 10ab5ba8 wininet!CCookieLocation::ReadCacheFile+0x47 (FPO: [Non-Fpo])
    06 074cfb88 71afbed3 10ab5ba8 00000000 11282fd8 wininet!CCookieLocation::ReadCacheFileIfNeeded+0x1c (FPO: [0,1,0])
    07 074cfbfc 71ac74ae 074cfc1c 10ab5ba8 11282fd8 wininet!HTTP_REQUEST_HANDLE_OBJECT::CreateCookieHeaderIfNeeded+0x231 (FPO: [Non-Fpo])
    08 074cfc44 71ac4ff8 11282fd8 71ac5020 074cfc68 wininet!HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_Start+0x41c (FPO: [1,11,4])
    09 074cfc5c 71ac4dc1 11282fd8 10ab5ba8 081ca040 wininet!CFsm_HttpSendRequest::RunSM+0x77 (FPO: [Non-Fpo])
    0a 074cfcb0 71acd160 081ca040 074cfce8 074cfd5c wininet!CFsm::Run+0x161 (FPO: [Non-Fpo])
    0b 074cfd8c 71acd511 bacfc17e 037b75d0 71acd4f0 wininet!CFsm::RunWorkItem+0x234 (FPO: [Non-Fpo])
    0c 074cfdc0 7753419c 074cfe2c 11282fd8 037b75d0 wininet!FailFastThreadPoolCallback<&CFsm::RunWorkItemWrapper>+0x21 (FPO: [SEH])
    0d 074cfde8 775417a8 074cfe2c 0766ebb8 bc65d1cc ntdll_77520000!TppSimplepExecuteCallback+0x6c (FPO: [Non-Fpo])
    0e 074cff80 77257c04 037b75d0 77257be0 bc339ed2 ntdll_77520000!TppWorkerThread+0x4f3 (FPO: [SEH])
    0f 074cff94 7757ab8f 037b75d0 bc65d190 00000000 KERNEL32!BaseThreadInitThunk+0x24 (FPO: [Non-Fpo])
    10 074cffdc 7757ab5a ffffffff 7755ffe8 00000000 ntdll_77520000!__RtlUserThreadStart+0x2f (FPO: [SEH])
    11 074cffec 00000000 77534930 037b75d0 00000000 ntdll_77520000!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

    0: kd:x86> du 12151430
    00000000`12151430  "C:\Users\xxxxx\AppData\Local\Mic"
    00000000`12151470  "rosoft\Windows\INetCookies\6WGHZ"
    00000000`121514b0  "Y5P.txt"
    ------------------------------------------------------------------------------------

    上記コール スタックを見ていただければわかると思いますが、Skype.exe の 32 ビット プロセス側から発行された KERNELBASE!CreateFileW コールは、Native API コールである ntdll_77520000!NtCreateFile コールに変換されたあと、Skype.exe の 64 ビット プロセス側の ntdll!NtCreateFile に渡されています。
    その後 sysenter によりカーネル モード側の nt!NtCreateFile ルーチン (ntoskrnl.exe 内) を経由して NTFS ドライバにファイル オープン リクエストが渡されていますが、この一連の処理はすべて Skype.exe プロセス内で行われています。

    Windows では、32 ビット プロセスは 2G Bytes のユーザー モード空間と 2G Bytes のカーネル モード空間の計 4G Bytes の仮想メモリ空間、64 ビット プロセスは 8T Bytes のユーザー モード空間と 248T Bytes のカーネル モード空間の計 256T Bytes の仮想メモリ空間を持ちます。
    つまり "System Process" 以外の一般のプロセスは、ユーザー モード空間とカーネル モード空間の2種類の仮想メモリ空間を持ち、同一プロセス空間内で必要に応じてユーザ モード空間とカーネル モード空間を行き来している訳です。
    ここら辺の詳細については、下記 MSDN サイト情報が参考になると思います。

    ------------------------------------------------------------------------------------
    仮想アドレス領域
    https://msdn.microsoft.com/ja-jp/library/windows/hardware/hh439648(v=vs.85).aspx
    ------------------------------------------------------------------------------------

    ただし、例外的にユーザ プロセスから発生した処理の一部が "System Process" 内で処理される可能性はあります。
    これはユーザ プロセス側から意図的にそうさせるのではなく、その処理に介在するドライバの実装に起因して発生します。
    デバイス ドライバやファイル システム ドライバ、あるいは何かのフィルタ ドライバ等のカーネル モード側で動作するドライバは、"System Process" 内で動作する System Worker Thread を利用することができます。
    カーネル モード側で動作するドライバは可能な限り素早く処理することが求められるため、時間のかかる処理や同一コンテキストで行う必要のない処理を、Work Item として System Woker Queue にポストし、"System Process" 内の System Worker Thread で実行させることができます。
    (この System Woker Queue にポストされた Work Item は、オリジナルのスレッド コンテキストは全く別の System Worker Thread で実行されます。)

    > カーネルモードのメモリ空間は単一でカーネルモードの
    > スレッドすべてで共有されていると理解しています。
    > その観点で、1つのプロセスと理解して差支えないわけですよね。
    > ただ、特定のユーザーモードプロセス・スレッドを起源にもつ
    > カーネルモードスレッドは、起源をちゃんと覚えている、
    > 自身の処理が終われば、元のユーザーモードプロセス・スレッドに
    > 制御を戻せる、わけですよね。
    > 現時点で、描いている姿はこんな感じです。

    カーネル モード空間は、すべてのプロセス間で共有されますが、だからと言ってカーネル モード空間が1つのプロセスであるという認識は、間違いだと思います。
    先にも示したように、アプリやサービス等の一般のプロセスにも、カーネル モード空間は存在しています。
    "System Process" がユーザ モード空間を持たないのは、単に持つ必要がないだけだと思います。
    言い換えれば、"System Process" はユーザ プロセスの様に、特定の機能に特化した処理を行うのではなく、様々なプロセスから付随して発生するシステムが管理すべき処理を行うために、独立したプロセスとしてい存在している。。。ということなんだと思います。
    例えば、さまざまなプロセスから発生するメモリの割り当て/解放処理では、その処理を任意のプロセス コンテキスト内だけで実現させることは不可能です (物理メモリの空き領域が不足している場合、そのプロセス内だけで物理メモリの使用状況を調整することは不可能です) し、各種周辺デバイスから発生するハードウェア割り込みを任意のユーザ プロセスで処理させたら、おそらくおかしなことになってしまうと思います。
    "System Process" はその名のとおり、システムが管理すべき処理を実行するためのプロセスであり、基本的にそのような処理は任意のアプリケーション (やサービス) から明示的にリクエストされるような性質のものではないため、ユーザ モード空間を持たない。。。ということなんだと思います。

    > Unix系だと「カーネルモードのプロセスは存在する」と説明されていて、
    > システムコールに際しては「on behalf of」ユーザープロセスとして
    > カーネルモードのスレッドを実行する、ということらしい・・・。
    > Windowsもこれと同じことか? というのが別の視点での知りたいポイントです。

    Unix 系のことはよくわかりませんが、Windows での "System Process" は確かにカーネル モード空間しか持たないプロセスですが、すべてのカーネル モード空間側の処理を行うプロセスではありません。
    任意のプロセス内で処理できるもの、あるいはそのスレッド コンテキストで処理すべきものについては、そのプロセス内の「カーネル モード空間」で処理されます。
    これは、"System Process" とは全く別次元の話です。

    すでに佐祐理さんも提案されますが、この手の詳細を知りたいのであれば、「インサイド Windows」 (原題 "Windows Internals") を読まれることをお勧めします。
    ただ (私だけが感じてることかもしれませんが) この本はとても難しいので、WinDBG 等のカーネル デバッガを使用して、実際の PC の挙動のを確認しながら読み進めるのが、一番効率的だと思います。
    (実際、この本の中でも WinDBG を使用した例が、多数掲載さています。)

    蛇足ですが。。。
    「インサイド Windows 第4版」の監修をされた豊田孝さんが、昔このフォーラムに参加されていました。
    今は御覧になっているかはわかりませんが。。。

    • 回答の候補に設定 星 睦美 2016年7月26日 5:53
    • 回答としてマーク 星 睦美 2016年7月29日 7:57
    2016年7月25日 8:17
  • お馬鹿さま(って、書くの、ちょっと何ですが・・・) 

    非常によくわかりました。実例を示して頂きながらの至極丁寧なご説明、深く感謝します。Windows Internalsは、是非入手しようと思います。小生もですが、職場の後輩にも読んでもらいたく。

    以下蛇足ながら本質問の背景を申し上げると、別の方の「スレッドと割り込み・・・」と題する一連の質疑で、実験における測定データの取り込みや機器制御を行う場合の、カーネルモードドライバとユーザーモードプログラムの動作の関係を整理しておきたいな、と感じた次第。

    重ね重ね、ありがとうございました。
    2016年7月25日 12:24