• ベストアンサー

プロセスのハンドルと識別子

エディットやボタンなどへのアクセスは、ウインドウハンドルを使ってそれらのオブジェクトにアクセスしているんだと考えられますが、 プロセスやスレッドにはハンドルと識別子の両方があるので、その違いが分かりません。 あるスレッドが動いていて、それを止める場合、そのスレッドのハンドルを使うのか識別子を使うのかが想像できるようになりたいのです。 プロセスを終わらせる関数を見つけ、その関数の引数の型を調べるのではなく、ハンドルと識別子の違いを理解して、それを想像する方法を教えてください。

  • setrs
  • お礼率15% (7/44)

質問者が選んだベストアンサー

  • ベストアンサー
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.1

OSを限定しないと正確な説明はできないので、ここではWindowsを仮定します。(他のOSの場合は補足願います。) グラフィックオブジェクト(エディットやボタンなど)の「ハンドル」と、カーネルオブジェクト(プロセスやスレッド)の「ハンドル」にはいくつか大きな違いがあります。 【グラフィックオブジェクトのハンドルの性質】 ・1つのオブジェクトに1つのハンドル番号が割り当てられる ・ハンドル番号の割り当てがシステム全体で重複しない ・どのプロセスからも同じハンドル番号で同じオブジェクトを参照できる 【カーネルオブジェクトのハンドルの性質】 ・1つのオブジェクトに複数のハンドル番号を割り当てることができる ・同じハンドル番号でも別のプロセスでは別のオブジェクトを指しているかもしれない ・同じハンドル番号でも別のプロセスでは無効かもしれない 例えば、プロセスAでウィンドウを作成し、そのハンドルが0x15e8だったとします。このとき別のプロセスBでハンドル0x15e8のウィンドウを操作すると、同じウィンドウを操作することになります。 これに対して、プロセスAでスレッドを作成し、そのハンドルが0x2ab0だったとします。このとき別のプロセスBでハンドル2ab0のスレッドを操作しようとしても、それが可能だとは限りません。 プロセスBがプロセスAのハンドルを「継承」しているか、プロセスBがスレッドの「識別子(ID)」を取得し、そこからプロセスB内で有効なハンドルを取得すれば、プロセスAのスレッドを操作することができるようになります。前者の場合、プロセスAの中で使用していたスレッドのハンドルがそのまま使えますが、後者の場合は同じ「プロセスAのスレッド」に対して、異なる値を持つ「プロセスB内で有効なハンドル」を取得することになります。 カーネルオブジェクトのハンドルはプロセスごとに割り当てられるので、システム全体を通じてハンドルを一覧することは通常はできません。しかしプロセスとスレッドに限っては、システム全体を通じての一覧ができないと不便です。そのため、プロセスとスレッドには特別に、システム全体を通じて一意であることが保証されている「識別子」が用意されています。 この「識別子」はグラフィックオブジェクトのハンドルと似た性質があります。 【プロセス識別子・スレッド識別子の性質】 ・1つのオブジェクト(プロセスまたはスレッド)に1つの識別子が割り当てられる ・識別子の割り当てがシステム全体で重複しない ・どのプロセスからも同じ識別子で同じオブジェクトを識別できる なお、識別子はオブジェクトを「識別」する(例えばスレッドAとスレッドBが同じか違うかを判断する)ためには使用できますが、オブジェクトの状態を「参照」・「操作(変更)」する(例えばスレッドAを停止する)ためには使用できません。識別子は「どのオブジェクトであるか」という情報を提供するだけだからです。 それ以上の情報の取得やオブジェクトの状態の操作は、プロセスごとにその参照・操作が許されているかどうかの設定(セキュリティ設定)があり、その設定を確認するためにオブジェクトを「開いて」ハンドルを取得する必要があります。 オブジェクトを開いてハンドルを取得する際には「オブジェクトに対してどういう操作を行うか」を指定します。このときシステムは、指定された操作が許されているかどうかをチェックします。ハンドルが取得できれば、その操作を行う権限があるということになります。 ハンドルと識別子の違いはこんなところです。

setrs
質問者

お礼

内容が難しくてあんまり分かりませんでしたが知りたかったことはかなり分かりました。 ウインドウオブジェクトの変更はハンドルを使うけど、別プロセスのウインドウオブジェクトに触れる時は、ハンドルよりもグローバルな識別子を使って目的のウインドウオブジェクトか確認してからハンドルを使ってウインドに触れるんですよね。 CreateProcessの継承は、プロセスのハンドルのスコープの幅に関するもので、オブジェクトの性質を継承するようなJAVA感覚の継承とは違う内容のようですね。 ありがとうございました。

関連するQ&A

  • windowsのプロセスIDやスレッドIDの使い道

    win32APIで取得したプロセスIDやスレッドIDの使い道について教えてください。 CreateProcessなどで取得したプロセスのハンドルやスレッドのハンドルはwin32APIで使う場面がありますが、プロセスIDやスレッドIDの使い道がわかりません。 どのような場面でプロセスIDやスレッドIDを使うのでしょうか?具体的にこんな事をするときに使うよなどあれば教えていただきたいです。 プロセスIDやスレッドIDを引数にとるAPI関数などがあれば教えていただきたいです。

  • 既存プロセスからプロセスのプライマリースレッドIDの取得方法

    いつもお世話になってます。 プロセスに関することで分からないことがあるため、どなたか御教授して下さい。 只今、VC++で開発を行っているのですが、CreateProcess関数を使用して開始したプロセスの情報が、引数で指定したPROCESS_INFORMATIONにプライマリースレッドのハンドルやIDが設定されるのは知っているのですが、現在動作中のプロセスからそのプロセスのプライマリースレッドのIDを取得することは可能でしょうか? 具体的には、動作中のプロセスIDを指定するとそのプロセスのプライマリースレッドに対してPostThreadMessageで任意のメッセージが送れるという仕様です。 対象のプロセスがウィンドウを持っていれば、EnumWindows関数を使用してウィンドウに対してPostMessageができるというのは分かったのですが、今回対象のプロセスがウィンドウを持たない為、上記のようにスレッドに対してメッセージを送るようになっています。 CreateProcess呼び出し時にはスレッドIDが取得できることから、プロセスID、または、プロセスハンドルからスレッドIDが取得できるのではないかなと考えられるんですが。。。。

  • スレッドが作れない

    VC9SDKで、スレッドを作る時_beginthreadexの第3引数の型でエラーが出てしまいます。 ・・・main(・・・){ HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &Process, NULL, 0, ID_PROCESS); } int __stdcall Process(){ } これはどう書けば解決するんでしょうか? お願いします。

  • [Haskell]handle関数がうまくいかない

    RealWorldHaskellという本を読んでいて解決できないところがあったので質問します。 Control.Exceptionには例外を扱うhandle関数というものがあります。 型シグネチャは Exception e => (e -> IO a) -> IO a -> IO a です。 1つ目の引数に例外を捉えた場合実行する関数を、2つ目の引数に例外を投げる可能性のある関数を与えます。 1つ目の引数の関数の返り値の型と2つ目の引数の型は同じでなければなりません。 次の関数はhandle関数を利用して安全にファイルサイズを取得する(つもりで作った)関数です。 getFileSize :: FilePath -> IO (Maybe Integer) getFileSize path = handle (\_ -> return Nothing ) $ bracket (openFile path ReadMode) hClose $ \h -> do size <- hFileSize h return (Just size) この関数がうまくいきません。 具体的に言えばコンパイルすると handle (\_ -> return Nothing ) の部分で Ambiguous type variable `e0' in the constraint: とエラーは吐きます。 しかし、返り値の型はNothingでMaybe Integerと合致していると思います。 なのにAmbiguousです。 なぜこうなるのかわかりません。 ちなみにControl.OldExceptionでもhandle関数が定義されていますが、ghcのバージョンが新しいせいか(7.0.2)コンパイルできません。 なのでControl.Exceptionしか使えません。 よろしくお願いします。

  • win32 スレッドのハンドルついて

    windowsのスレッドについての質問です。 今、手元にある書籍のスレッドを作る節にCreateThread()関数を使ってスレッドを作るサンプルプログラムが載っています。 その中では CloseHandle()関数が一切呼ばれていません。 しかも、そのサンプルではいくつもスレッドを作り、そのスレッドはプログラム中でいくつも終了するようなものです。CloseHandle()は呼び出さなくても問題ないのでしょうか? しかし、ネットで調べてみるとCloseHandle()を呼び出さなくてはいけないということが書かれていました。 http://www.daccho-it.com/program/WinApi/thread.htm ↑ 参考にしたサイト そこでいくつか質問です。 プロセスが終了するときにスレッドのハンドルは自動的に閉じられるという認識で大丈夫でしょうか? CreateThread()、_beginthreadex関数はCloseHandle()を呼び出す必要があるで大丈夫でしょうか? となると、CreateThread()の戻り値は必ず変数に保存しておく必要があるということですか? 書籍のサンプルではCreateThread()の戻り値はどこにも保存していませんでした、保存しない場合ハンドルが作られないってことはさすがにないですよね? よろしくお願いします。

  • HANDLEとHWNDの違いについて

    HANDLE と HWND の違いについて自分なりにノートにまとめようとしています。HANDLEとは、ウインドウを識別するためのものだと思っていました。 となると、HWNDも同じ説明になり、やはり理解が間違っていたのかと思います。 ご存知の方がいらしゃいましたら教えたください。

  • 別プロセスの起動

    別プロセスの起動について質問があります。 Java、Servlet、JSPを使って検索画面、検索処理を作っています。 レコード件数が何万件もあるので、検索処理を別プロセス(別クラス)で実行したいと考えています。 クラス構成は、 1.検索条件受け取りクラス 2.検索処理クラス 検索条件受け取りクラスで、検索条件をオブジェクトにし、そのオブジェクトを検索処理クラスの引数に渡し、別プロセスとして実行するような感じで考えています。 ※スレッドでの実装は、メモリを消費するため考えておりません。 実装方法やサンプルをよろしくお願いします。

  • スレッド内でのマルチスレッドの作成[WINDOWSプログラミング]

    いつもお世話になっております。 現在WINDOWSプログラムでゲームを最中なのですが、スレッド内でスレッドを作成できなくて困っています。 キャラを動かすスレッドで以下の関数を使い、スレッドを作成しようとしたのですが、 CreateThread(NULL, 0, ATK, (LPVOID)&x, 0, &dwID); 以下のようなエラーメッセージが出てしまいます。 'ATK':定義されていない識別子です '関数' : 間接参照のレベルが 'LPTHREAD_START_ROUTINE' と 'int' で異なっています。 'CreateThread' : の型が 3 の仮引数および実引数と異なります。 わかる方いましたらどうがご指導お願いします。 初歩的なミスでしたらすみません。

  • 【C++】セマフォとプロセスの使い方

    【C++】セマフォとプロセスの使い方 WindowsXPでVC++2008コンパイラを使用して、 プロセスとセマフォについて勉強しています。 外部プログラム(今回は電卓として)を5つ立ち上げるのですが、 同時に立ち上げるのは2つまでとしたい場合、どのように組むのでしょうか。 http://nienie.com/~masapico/api_CreateSemaphore.html こちらにスレッドを使用したセマフォを使ったサンプルがあるのでが、 プロセスを使うとなると、うまく書けません。 ご指導頂けませんでしょうか。 ===現在まで書いたソース=== (5つのプロセスをつくるループも実装していませんが、、、) #include<windows.h> #include<stdio.h> #include<tchar.h> HANDLE g_hSemaphre; void main(){ BOOL bRet; STARTUPINFO si; PROCESS_INFORMATION pi; //Semaphoreオブジェクト g_hSemaphre = CreateSemaphore(NULL,2,2,NULL); bRet = CreateProcess(_T("C:\\WINDOWS\\system32\\calc.exe"), _T(""), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); //プロセス終了 WaitForSingleObject(pi.hProcess,INFINITE); //後処理(プロセス開放) ReleaseSemaphore(g_hSemaphre,1,NULL); //スレッドとプロセスを閉じる。 CloseHandle(pi.hThread); CloseHandle(pi.hProcess); //Semaphoreオブジェクト CloseHandle(g_hSemaphre); }

  • マルチスレッドについて

    現在”猫でもできる”の87、88章を学んでおります。 まず87章でマルチスレッドの根本的なやり方を学びましたが、いきなり疑問が浮かびました。 _beginthread関数によりスレッドをスタートさせ、この関数で登録した関数内で_endthread関数を実行し終了させていることは分かります。 しかし_beginthread関数で登録した関数に引数を渡す処理がどの部分で行われているのかわかりません。 登録する関数はvoid型で引数はvoid*型でなければいけないことは分かったのですが、プログラムのどこを見てもこの登録した関数に引数を渡す処理が行われていません。 その辺の動作の説明を分かる方でいいのでよろしくお願いします。 そして88章では排他制御のマルチスレッドを行うプログラムの製作を行っているのですが、ちょっとした疑問が浮かびました。 EnterCriticalSection関数、LeaveCriticalSection関数ではさまれたプログラムは排他制御され他からアクセスされない。 この関数はこんな理解で良いんですかね? この理解で行くと、88章で説明していきますが、子ウィンドウを2つ作成しそれぞれのプロシージャ内で排他制御された関数をスレッドとしてスタートしています。 この2つのスレッドの動作についてですが、互いに排他制御関数が記述されているため、動作としてはまず左の子ウィンドウのスレッドが処理されている場合、右の子ウィンドウのスレッドは停止している。そして左の子ウィンドウのスレッドの排他制御が解放されたときに、右の子ウィンドウのスレッドが開始する。 そしてあるとき左の子ウィンドウのクライアントウィンドウ内で右クリックされた場合、その時点で排他制御されたスレッドが終了するのを待ち、終了したらcountを+1する。 こんな動作が行なわれていると理解してよいのでしょうか?

専門家に質問してみよう