このX11ウィンドウを作成するプロセスは何ですか?

このX11ウィンドウを作成するプロセスは何ですか?

X11ウィンドウIDが与えられたら、それを生成したプロセスのIDを見つける方法はありますか?

もちろん、これは常に可能なわけではありません。たとえば、ウィンドウがTCP接続から出る場合です。この場合、リモート側に接続されたIPとポートが必要です。

この質問は、以前Stack Overflowで質問されたことがあります。で推奨されるアプローチは、この_NET_WM_PIDプロパティを使用することです。ただし、これはアプリケーションによって設定されます。アプリケーションが正しく実行されていない場合にこれを行う方法はありますか?

答え1

XサーバーがXResQueryClientIdsサポートしていない限りX-リソース v1.2 拡張わからないシンプル続く安定してプロセスIDを要求しています。しかし、他の方法もあります。

前にウィンドウだけがまだIDがわからない場合は、見つけるのは簡単です。問題のあるウィンドウの横にある端末を開き、端末を起動してxwininfoウィンドウをクリックします。xwininfoウィンドウIDが表示されます。

したがって、0x1600045というウィンドウIDを知っていて、それを所有するプロセスを探したいとしましょう。

ウィンドウが誰に属しているかを確認する最も簡単な方法は、XKillClientを実行することです。例:

xkill -id 0x1600045

どのプロセスが終了したかを確認してください。でももちろん殺すのが気に入らない場合のみ!

_NET_WM_PID単純だが信頼できないもう1つの方法は、sum属性を確認することですWM_CLIENT_MACHINE

xprop -id 0x1600045

それがまさにツールxlsclientsのようなものです。xrestopする。

残念ながら、この情報は不正確かもしれません。プロセスが邪悪でそれを変更するだけでなく、エラーがあるからです。たとえば、いくつかのFirefoxがクラッシュ/再起動した後、ずっと前に死んだ_NET_WM_PIDプロセスを指す孤立したウィンドウ(フラッシュプラグインからのようです)を見ました。

もう一つの方法は走ることです。

xwininfo -root -tree

そして、そのウィンドウの親ウィンドウのプロパティを確認してください。また、ウィンドウのソースに関するいくつかのヒントを提供することもできます。

しかし!どのプロセスがウィンドウを作成したかを見つけることができないかもしれませんが、プロセスがどこでXサーバーに接続しているかを見つける方法があります。この方法は実際のハッカーに適しています。 :)

低いビットがクリアされた(例:0x1600000)、ウィンドウID 0x1600045として知られているのは「クライアントベース」です。このクライアントに割り当てられたすべてのリソースIDはこれを「ベース」にします(0x1600001、0x1600002、0x1600003など)。 Xサーバーはクライアントに関する情報をclient []配列に格納し、各クライアントの「デフォルト」はclient [i] -> clientAsMask変数に保存されます。そのクライアントに対応するXソケットを見つけるには、X-serverへの接続を使用し、gdbクライアント[]配列を繰り返し、その配列を使用してクライアントを探し、clientAsMask((OsCommPtr)(クライアントに格納されているソケット記述子を印刷する必要があります) . [i]->osPrivate))->fd.

接続されているXクライアントが多い可能性があるため、手動で確認したくない場合は、gdb関数を使用します。

define findclient
  set $ii = 0
  while ($ii < currentMaxClients)
    if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0)
      print ((OsCommPtr)(clients[$ii]->osPrivate))->fd
    end
    set $ii = $ii + 1
  end
end

ソケットを見つけたら、誰が接続したかを確認し、最終的にプロセスを見つけることができます。

警告する処置: Xサーバー内でgdbをXサーバーに接続しないでください。 gdbは接続プロセスを中断するため、Xセッション内で接続するとXサーバーがハングし、gdbと対話できなくなります。テキスト端末(Ctrl+Alt+F2)に切り替えるか、SSH経由でコンピュータに接続する必要があります。

例:

  1. XサーバーのPIDを見つけます。

    $ ps ax | grep X
     1237 tty1     Ssl+  11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
    
  2. ウィンドウIDは0x1600045なので、クライアントベースは0x1600000です。 Xサーバーに接続し、クライアントライブラリのクライアントソケット記述子を見つけます。 X-serverのデバッグ情報をインストールする必要があります(rpmディストリビューションの場合は-debuginfoパッケージ、debの場合は-dbgパッケージ)。

    $ sudo gdb
    (gdb) define findclient
    Type commands for definition of "findclient".
    End with a line saying just "end".
    >  set $ii = 0
    >  while ($ii < currentMaxClients)
     >   if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0)
      >     print ((OsCommPtr)(clients[$ii]->osPrivate))->fd
      >     end
     >   set $ii = $ii + 1
     >   end
    >  end
    (gdb) attach 1237
    (gdb) findclient 0x1600000
    $1 = 31
    (gdb) detach
    (gdb) quit
    
  3. これで、クライアントがサーバーソケット31に接続されていることがわかります。lsofそのソケットが何であるかを調べるには、次のようにします。

    $ sudo lsof -n | grep 1237 | grep 31
    X        1237    root   31u   unix 0xffff810008339340       8512422 socket
    

    (ここで、「X」はプロセス名、「1237」は対応するpid、「root」は実行されているユーザー、「31u」はソケット記述子です。)

    ここでは、TCPを介して接続されているクライアントを表示し、接続されたコンピュータに移動してnetstat -napプロセスを見つけることができます。ただし、上記のようにUnixソケットが表示される可能性が高く、これはローカルクライアントであることを意味します。

  4. このUnixソケットのペアを見つけるには、次のものを使用できます。MvGの技術 (インストールされたカーネルのデバッグ情報も必要です):

    $ sudo gdb -c /proc/kcore
    (gdb) print ((struct unix_sock*)0xffff810008339340)->peer
    $1 = (struct sock *) 0xffff810008339600
    (gdb) quit
    
  5. これでクライアントソケットがわかったので、それを使用してlsofそれを保持するPIDを見つけることができます。

    $ sudo lsof -n | grep 0xffff810008339600
    firefox  7725  username  146u   unix 0xffff810008339600       8512421 socket
    

それはすべてです。このウィンドウを保持するプロセスは「firefox」で、プロセスIDは7725です。


2017年編集:これで、以下のように多くのオプションがあります。このUnixソケットペアの反対側の端を持っている人はいますか?。 Linux 3.3以降およびlsof4.89以降の場合は、上記の3〜5番目の項目を次のように置き換えることができます。

lsof +E -a -p 1237 -d 31

IDが1237のXサーバープロセスのfd 31ソケットの反対側に誰がいるかを確認してください。

答え2

xdotool私には適していません。こうしました:

走る

xprop _NET_WM_PID

そしてウィンドウをクリックしてください。

これは以下に基づいています。Linuxの問題でXウィンドウのPIDを見つける

答え3

お持ちの場合xdoツールその後、インストールが完了しました

xdotool selectwindow getwindowpid

その後、そのウィンドウをクリックするとPIDが返されます。

(関連するウィンドウを選択する別の方法があります。たとえば、そのウィンドウIDがあればそれを行うことができます。xdotool getwindowpid <number>名前やクラスなどで選択することもできます。)

私はこれがWMをうまくやるべきだと思います。実験をたくさんしてみることもなく、実験をたくさんする必要もありません。

答え4

xdotoolUbuntu 11.04ベータ版で動作させることができましたが、これはselectwindow有効なコマンドではなく、次のようにスクリプトをハックする必要がありました。

$ while true; do sleep 1; xdotool getactivewindow; done

次に、目的のウィンドウが選択されたら、ウィンドウIDを確認し、次を使用して担当PIDをデコードします。

$ xdotool getwindowpid <the-window-id>

関連情報