プロセスIDとプロセスハンドルについて質問。

解決


ぴょぴょ  2007-11-13 18:02:40  No: 66809

プロセスIDはWindowsシステムにおいて重複しないための整数値と聞きました。
それでハンドルとは1つのプロセス内で通用する重複しないポインタのようなものと考えています。
もう少しきちんと表現すると「ハンドル」=「仮想メモリのアドレスを示す」ですよね。
ここで疑問があります。

プロセスIDからプロセスのハンドルを取得するには次のようになるようです。
(ネット検索より)

hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, 任意のプロセスID );

ここで取得できたプロセスのハンドルを使えば任意のプロセスID(別のプロセス)のハンドルを
取得したことになるのでしょうか?
もしこのプロセスハンドルでカレントプロセス以外の情報をいろいろと取得できるとするとなぜできるの?
ハンドルとは自分自身のプロセス内で通用する仮想メモリのアドレスなのに別の仮想メモリのアドレスとして識別できるのか?
ここをお聞きしたいです。
分かりやすい解説。
お願い致します。


tetrapod  2007-11-13 18:47:02  No: 66810

> 「ハンドル」=「仮想メモリのアドレスを示す」ですよね。
(仮に実装がそうであったとしても)そんな妄想は捨ててしまえ
概念上は [ハンドル=別名] だ (だから *ハンドルネーム* っつーのは馬から落馬)
別名というのがわかりにくければ「識別するに足る固有の数値」

プロセスIDは当該マシン上で固有の識別数値
だからどのプロセスから見ても abc.exe のプロセスIDは同じ
異なるマシン上では異なるプロセスであっても同じプロセスIDがありうる

ハンドルは当該プロセス上で固有の識別数値
だから abc.exe を OpenProcess した結果はプロセスごとに違う可能性がある
プロセスが違えば、同じ値のハンドルであっても内容は異なる

このプロセス上から見たハンドル *** は (という形でOSは区別を行い)
それがあらわすものは、開き済みファイルだとかプロセスだとか、
書き込み権限があるとか無いとか、そういう識別をしてくれるわけだ。

[読み込み専用権限で開き済みファイル]の別名 = ハンドル
[query_info 権限ありでプロセス yy を取り扱う]ための別名 = ハンドル
といえばわかるかな?


シャノン  2007-11-13 21:02:09  No: 66811

tetrapod さんもおっしゃってますが、ハンドル=ポインタと考えないほうがいいです。

abc.exe というプロセスがあったとして、
xxx.exe 内で abc.exe を OpenProcess したときのハンドル値と
yyy.exe 内で abc.exe を OpenProcess したときのハンドル値は
異なる可能性があります。

xxx.exe 内で abc.exe を OpenProcess したときに得られるハンドルは、xxx.exe 内でだけ有効な abc.exe のハンドルです。
yyy.exe 内で abc.exe を OpenProcess したときに得られるハンドルは、yyy.exe 内でだけ有効な abc.exe のハンドルです。
いずれのハンドルも、abc.exe 内で有効なものではありません。


シャノン  2007-11-13 21:05:54  No: 66812

ちと補足。
プロセスハンドル値は、OpenProcess を呼ぶたびに異なる値が返されることがあります。
プロセスハンドルとプロセスIDは1対1に対応しません。


tetrapod  2007-11-14 00:51:33  No: 66813

別な例を思いついたので

プロセスID = ファイル名 と思えばいい。
ファイルはどのプロセスから見ても同じ名前でアクセスできる (プロセス間共通)
マシンが違えばファイル名が同一でも、当然別のファイルである
プロセスIDも同じこと。

プロセスハンドルとはプロセスを開いた値
ファイルハンドルとはファイルを開いた値
これもまた同じと考えていい。
同一ファイルを(複数/異なる指定で)開けば異なるファイルハンドルが得られる。
同一プロセスを(複数/異なる指定で)開けば異なるプロセスハンドルが得られる。
# 開けるかどうかはまた別問題だが

ファイル名を指定してもファイルのサイズは得られる FindFirstFile
ファイルハンドルを指定してもファイルのサイズは得られる GetFileSize
似たようなことができるがファイルとファイルハンドルは違うよな

ハンドルは抽象的なもので実装を気にしちゃいかん、とだけわかればそれでいいよ。


ぴょぴょ  2007-11-14 18:22:24  No: 66814

tetrapodさん。
シャノンさん。
何度も読み返してやっと分かりました。

> プロセスハンドル値は、OpenProcess を呼ぶたびに異なる値が返されることがあります。
> プロセスハンドルとプロセスIDは1対1に対応しません。
最初は「ハンドル」=「仮想メモリのハンドルを示す」と考え、
無理やりC言語風で「ハンドル」を表現するとポインタのポインタと思っていました。

それから「プロセスID」OpenProcess すれば必ず同じ値の「プロセスハンドル」の値が
戻ってくるのかと思ってしまいました。いろいろとネット検索したら違いましたね。

結局、任意のプロセスID(別のプロセス)を OpenProcess でプロセスハンドルを取得すると
そのハンドルにアクセスすれば別のプロセスの情報を取り出せるための管理メモリが
「プロセスハンドル」で作成され、ハンドル値は取得するたびに異なることもあるという
解釈であっていますか?


シャノン  2007-11-14 18:52:36  No: 66815

> 結局、任意のプロセスID(別のプロセス)を OpenProcess でプロセスハンドルを取得すると
> そのハンドルにアクセスすれば別のプロセスの情報を取り出せるための管理メモリが
> 「プロセスハンドル」で作成され、ハンドル値は取得するたびに異なることもあるという
> 解釈であっていますか?

うーん…
合っていると言えば合っているんですが、どうしても「メモリ」が気になりますか?


ぴょぴょ  2007-11-14 20:11:34  No: 66816

シャノンさんへ。
もう一度書き直します。

結局、任意のプロセスID(別のプロセス)を OpenProcess でプロセスハンドルを取得すると
そのハンドルにアクセスすれば別のプロセスの情報を取り出せるための管理情報が作成される。
この「管理情報を示す」アドレスがハンドル値となる。ちなみにアドレスとは仮想メモリに
対するもので物理メモリの実アドレスではないです。

今現在、プロセス、スレッド、仮想メモリのお勉強をしています。
それで1つのプロセスでは最大 4G バイトのメモリ空間があり下位の 2G バイトを扱える。
でも実際の物理メモリはそんなにはないから、最近使われていないページ単位のメモリを
ページングファイルに「ページアウト」する。ページアウトしたメモリをアクセスすると
自動的に「ページイン」される。

それで最終的には別プロセスの仮想メモリ空間の利用状況をリスト作成したいのです。
この作成中にちょっとした疑問(今回の疑問)が出たわけ。ハンドルは自分自身のプロセスで
有効な値なのに Windows OS はどうして別プロセスの情報を「プロセスハンドル」の取得だけで
取り出せるの?ってね。

質問する前に「プロセスハンドル」が別プロセスの仮想メモリ空間のアドレスを表していると
思い違いをしていたようです。正しくは「プロセスハンドル」内の情報に別プロセスを取得
できるような情報も含まれるから「プロセスハンドル」を使えば Windows OS が別プロセスの
情報を指していると分かる。よって正常に取得できるということですよね。

これで解釈はあっているかな。


シャノン  2007-11-15 04:03:09  No: 66817

> 結局、任意のプロセスID(別のプロセス)を OpenProcess でプロセスハンドルを取得すると
> そのハンドルにアクセスすれば別のプロセスの情報を取り出せるための管理情報が作成される。

たぶんね。保証はありません。

> この「管理情報を示す」アドレスがハンドル値となる。

その思い込みを捨てなさい、と言われているでしょう?
管理情報構造体のアドレスかもしれませんが、そうでないかもしれません。
そして、アドレスであろうが無かろうが、使い方は変わらないのです。

> でも実際の物理メモリはそんなにはないから、最近使われていないページ単位のメモリを
> ページングファイルに「ページアウト」する。ページアウトしたメモリをアクセスすると
> 自動的に「ページイン」される。

仮想アドレス空間は実メモリ(マザーボードに装着されたメモリモジュール)とページングファイルのみではなく、その他のファイルマッピングオブジェクトや、どんな物理ストアにも割り当てられていない領域からなる。
アドレス空間は原則としてプロセスごとに独立しているが、ページングファイルやファイルマッピングオブジェクトを使うと共有することができる。

プロセスのアドレス空間の上位2GBはカーネルによって利用され、すべてのプロセスで共有される(…たぶん。間違えていたらつっこんで)。
で、プロセスやスレッド、イベント等のカーネルオブジェクトの情報構造体は、この上位領域に置かれている。
OpenProcess したタイミングで、この管理情報がユーザ領域(下位2GB)にコピーされるのか、それともカーネルメモリを直接参照しているのかはわからない。

> それで最終的には別プロセスの仮想メモリ空間の利用状況をリスト作成したいのです。

そういうマニアックなプログラミングは大好きです。
応援しますよ。がんばって。


ぴょぴょ  2007-11-15 08:13:39  No: 66818

返信ありがとうございます。

> たぶんね。保証はありません。
タスクマネージャで「svchost.exe」の「ユーザ名」に「NETWORK SERVICE」「LOCAL SERVICE」が
OpenProcess でプロセスハンドルを取得できないみたいです。でも「SYSTEM」となっているものは
取得できる。なぜ?この違いの仕組みは分かりますか?

> その思い込みを捨てなさい、と言われているでしょう?
ちょっと前に言われた。
自分なりに分かりやすくイメージして精一杯に表現したのだけなのに…。

> 管理情報構造体のアドレスかもしれませんが、そうでないかもしれません。
> そして、アドレスであろうが無かろうが、使い方は変わらないのです。
分かりやすくそのような仕組みだろ〜なと思ったわけ。
確かに実際にどうなっているか不明ですね。

今日は次のリンクを読みました。
http://itpro.nikkeibp.co.jp/article/COLUMN/20071107/286607/
まだ全て理解できていないです。1、2は理解できたけどそれ以外は…。です。
昨日は次のリンクを読んでいました。
http://itpro.nikkeibp.co.jp/article/COLUMN/20070126/259762/
http://itpro.nikkeibp.co.jp/article/COLUMN/20070416/268374/
http://itpro.nikkeibp.co.jp/article/COLUMN/20070603/273403/
http://itpro.nikkeibp.co.jp/article/COLUMN/20070816/279802/
まだ1回しか読んでいないためすべては理解できていないのかもしれない。
もう一度読み直すつもりです。
特に第4回 メモリー管理のキー技術「仮想メモリー」を知る。などを。

> そういうマニアックなプログラミングは大好きです。
> 応援しますよ。がんばって。
はい。頑張ります。

また何かあればお願いします。


シャノン  2007-11-15 09:57:11  No: 66819

> タスクマネージャで「svchost.exe」の「ユーザ名」に「NETWORK SERVICE」「LOCAL SERVICE」が
> OpenProcess でプロセスハンドルを取得できないみたいです。でも「SYSTEM」となっているものは
> 取得できる。なぜ?この違いの仕組みは分かりますか?

OSにもよるので何とも言えません。
VistaとXP以前では全然違うでしょうし。

> 今日は次のリンクを読みました。

面白そうな連載ですね。


ぴょぴょ  2007-11-15 20:39:11  No: 66820

> OSにもよるので何とも言えません。
> VistaとXP以前では全然違うでしょうし。
そうですか。

> 面白そうな連載ですね。
もう一度よく読んでみます。

tetrapod さん。
シャノンさん。
ありがとうございました。

これで一応の解決とします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加