4

CRITICAL_SECTION ロック (enter) とロック解除 (leave) は、ミューテックスが行うカーネル システム コールを行わずに CS テストがユーザー空間で実行されるため、効率的です。ロック解除は完全にユーザー空間で実行されますが、ReleaseMutex にはシステム コールが必要です。

この本でこれらの文を読んだところです。
カーネル システム コールの意味 関数の名前を教えてください。

私は英語初心者です。私はそれらをこのように解釈しました。

  • CS テストはシステム コールを使用しません。
  • ミューテックスのテストはシステムコールを使用します。(関数名がわからないので教えてください)
  • CSロック解除はシステムコールを呼び出しません。
  • ミューテックスのロック解除にはシステムコールが必要です。(関数名がわからないので教えてください)

別の質問です。

  • CRITICAL_SECTION は WaitForSingleObject またはファミリ関数を呼び出す可能性があると思います。これらの関数はシステムコールを必要としませんか? そうだと思います。したがって、CS テストでシステム コールが使用されないことは、私にとって非常に奇妙です。
4

4 に答える 4

5

Windows でのクリティカル セクションの実装は長年にわたって変更されてきましたが、常にユーザー モードとカーネル呼び出しの組み合わせでした。

CRITICAL_SECTION は、ユーザー モードで更新された値、カーネル モード オブジェクト (EVENT など) へのハンドル、およびデバッグ情報を含む構造体です。

EnterCriticalSection は、ロックを取得するために連動テスト アンド セット操作を使用します。成功した場合、必要なのはこれだけです (ほとんどの場合、所有者スレッドも更新されます)。test-and-set 操作が取得に失敗した場合は、より長いパスが使用されます。これには、通常、カーネル オブジェクトを で待機する必要がありますWaitForSignleObjectInitializeCriticalSectionAndSpinCountthenで初期化した場合EnterCriticalSection、ユーザーモードでの連動操作を使用して取得するためにリトライをスピンする場合があります。

EnterCriticialSection以下は、 Windows 7 (64 ビット)の「高速」/競合のないパスの逆アセンブリであり、いくつかのコメントがインラインで示されています。

0:000> u rtlentercriticalsection rtlentercriticalsection+35
ntdll!RtlEnterCriticalSection:
00000000`77ae2fc0 fff3            push    rbx
00000000`77ae2fc2 4883ec20        sub     rsp,20h
; RCX points to the critical section rcx+8 is the LockCount
00000000`77ae2fc6 f00fba710800    lock btr dword ptr [rcx+8],0
00000000`77ae2fcc 488bd9          mov     rbx,rcx
00000000`77ae2fcf 0f83e9b1ffff    jae     ntdll!RtlEnterCriticalSection+0x31 (00000000`77ade1be)
; got the critical section - update the owner thread and recursion count
00000000`77ae2fd5 65488b042530000000 mov   rax,qword ptr gs:[30h]
00000000`77ae2fde 488b4848        mov     rcx,qword ptr [rax+48h]
00000000`77ae2fe2 c7430c01000000  mov     dword ptr [rbx+0Ch],1
00000000`77ae2fe9 33c0            xor     eax,eax
00000000`77ae2feb 48894b10        mov     qword ptr [rbx+10h],rcx
00000000`77ae2fef 4883c420        add     rsp,20h
00000000`77ae2ff3 5b              pop     rbx
00000000`77ae2ff4 c3              ret

つまり、スレッドがブロックする必要がない場合、スレッドはシステム コールを使用せず、インターロックされたテストと設定の操作だけを使用します。ブロックが必要な場合は、システム コールが発生します。リリース パスも連動したテスト アンド セットを使用し、他のスレッドがブロックされている場合はシステム コールが必要になる場合があります。

これを、常にシステム コールNtWaitForSingleObjectを必要とする Mutex と比較してください。NtReleaseMutant

于 2011-05-21T05:01:27.833 に答える
4

カーネルを呼び出すには、コンテキスト スイッチが必要です。これは、コンテキスト スイッチごとに小さな (ただし測定可能な) パフォーマンス ヒットになります。問題の関数はReleaseMutex()それ自体です。

クリティカル セクション関数はkernel32.dll(少なくとも呼び出し元の観点からは - に関する議論についてはコメントを参照してくださいntdll.dll) で利用でき、多くの場合、カーネルへの呼び出しを回避できます。

Mutex オブジェクトは、異なるプロセスから同時にアクセスできることを知っておく価値があります。一方、CRITICAL_SECTIONオブジェクトは 1 つのプロセスに限定されます。

于 2011-03-03T02:55:05.093 に答える
1

私の知る限り、クリティカル セクションはセマフォを使用して実装されています。

クリティカル セクション関数は NTDLL で実装されます。NTDLL は、ユーザー モードでいくつかのランタイム関数を実装し、制御をカーネルに渡します (システム コール)。kernel32.dll の関数は単純な関数フォワーダーです。

一方、ミューテックスはカーネル オブジェクトであり、システム コール自体が必要です。ちなみに、カーネルはそれらを「ミュータント」と呼んでいます(冗談ではありません)。

于 2011-03-03T03:06:50.690 に答える
1

クリティカル セクション コールは、競合が発生し、スピンによって競合を解消できない場合にのみ、カーネル モードに移行します。その場合、スレッドはブロックされ、待機関数を呼び出します。これがシステム コールです。

于 2011-03-03T07:19:58.173 に答える