モニターが接続されているか、接続されていないかを検出するにはどうすればよいですか?


53

私のラップトップのDisplayPortに外部モニターをプラグインまたはアウトするときにトリガーされるイベントはありますか?ACPIDとUDEVはまったく反応しません。

Intelチップのオンボードグラフィックスを使用しています。ここでは、すでに数年古い同様の議論があります。

ポーリングを使用したくありませんが、ディスプレイが接続されているかどうかに応じてディスプレイ設定を自動的に設定する構成が必要です。


4
それはudevで実行できます。カーネルのバージョンは何ですか?KMS(カーネルモード設定)を使用していますか?
アンディ

答えてくれてありがとう。KMSについてはわかりませんが、質問で述べたように、udevはイベントを送信しません。(udevadm monitor --propertyはまったく反応しません)
-janoliver

@アンディ:これが最後に登場したとき、ほとんどのシステムがポーリングを必要とするようでした。udevイベントをトリガーする方法を見つけた場合、その質問に答えられますか?
ジル「SO-悪であるのをやめる」

1
ついに、i915をカーネルモジュールとしてロードして実行しました。
janoliver

3
xrandrまたはdisperを使用して、外部モニターが接続されているかどうかを検出できます。github.com/ wertarbyte / autorandrは、それらの使用方法を示すことができます。ただし、xrandr / disperはビデオカードをサポートしていない場合があります。
number5

回答:


13

注: これは、i915駆動のグラフィックスカードを搭載したラップトップでテストされました。


バックグラウンド

注:新しい画面がプラグインされると、イベントはホストに送信されません。これは、最後の編集後もそのままでした。したがって、唯一の方法はポーリングを使用することです。それらを可能な限り効率的にしようとしています...

編集#3

最後に、より良い解決策が1つあります(ACPIを使用)。

イベントはまだありませんが、ACPIはxrandr問い合わせるよりも効率的です。(注:これに ACPIカーネルモジュールをロードする必要がありますが、ルート権限は必要ありません)。

私の最終的な解決策(bashを使用):

isVgaConnected() {
    local crtState
    read -a < /proc/acpi/video/VID/CRT0/state crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

今テスト:

$ if isVgaConnected; then echo yes; else echo no; fi 
yes

プラグインされているので、プラグを外します。

$ if isVgaConnected; then echo yes; else echo no; fi 
no

注: ブール引数を${1:+*-1+1}許可:何かが存在する場合、答えは逆になります:。( crtState >> 4 ) * -1 + 1

最後のスクリプト:

#!/bin/bash

export crtProcEntry=/proc/acpi/video/VID/CRT0/state

isVgaConnected() {
    local crtState
    read -a < $crtProcEntry crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

delay=.1
unset switch
isVgaConnected || switch=not
while :;do
    while isVgaConnected $switch;do
        sleep $delay
      done
    if [ "$switch" ];then
        unset switch
        echo VGA IS connected
        # doing something while VGA is connected
      else
        switch=not
        echo VGA is NOT connected.
        # doing something else, maybe.
      fi
  done

警告: Bashスクリプトは、より軽く、xrandr重要はない0.02秒未満の遅延で、リソースを食べるプロセスの最上位に移動します(top)!

これには約0.001秒かかりますが:

$ time read -a </proc/stat crtStat

これには、〜0.030秒が必要です。

$ read -a < /proc/acpi/video/VID/CRT0/state crtState

これは大きい!必要なものに応じてdelay0.5との間に合理的に設定できます2

編集#2

私はこれを使用して最終的に何かを見つけました:

重要な免責事項:で遊ぶ/proc/sysエントリーがシステムを破壊する可能性があります!!! そのため、実稼働システムでは以下を試さないでください。

mapfile watchFileList < <(
    find /sys /proc -type f 2>/dev/null |
    grep -i acpi\\\|i91 
)

prompt=("/" "|" '\' '-');

l=0
while :; do
  mapfile watchStat < <(
    grep -H . ${watchFileList[@]} 2>/dev/null
  )

  for ((i=0;i<=${#watchStat[@]};i++)); do
    [ "${watchStat[i]}" == "${oldStat[i]}" ] || echo ${watchStat[i]}
  done

  oldStat=("${watchStat[@]}")
  sleep .5
  printf "\r%s\r" ${prompt[l++]}
  [ $l -eq 4 ]&&l=0
done

...不要なエントリをいくつか削除した後:

for ((i=0;i<=${#watchFileList[@]};i++)); do
  [[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
      unset watchFileList[$i] && echo $i
done

私はこれを読むことができました:

/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d

モニターケーブルを接続、取り外し、再接続するとき。

元の回答

構成が(実行中system/preferences/monitorまたはxrandr)照会されると、グラフィックカードはscanのタイプを実行するため、実行xrandr -qすると情報が提供されますが、ステータスをポーリングする必要があります。

すべてのログ(カーネル、デーモン、Xなど)をスキャンし、/proc&を検索しました/sysが、明らかに要求を満たすものは何も存在しないようです。

私もこれを試しました:

export spc50="$(printf "%50s" "")"
watch -n1  '
    find /proc/acpi/video -type f |
        xargs grep -H . |
        sed "s/^\([^:]*):/\1'$spc50'}:/;
             s/^\(.\{50\}\) *:/\1 /"'

結局のところ、System/Preferences/Monitor新しい画面がプラグインされていない状態でもプラグインされていない状態でも実行すると、ツールは単純に(通常)表示されます。ただし、以前に画面を接続または切断したことがある場合、このツールを実行すると、デスクトップでリセットまたは更新が行われることがあります(実行した場合と同じですxrandr)。

これは、xrandr実行時に開始して定期的にステータスをポーリングすることで、このツールが要求する(または同様に機能する)ことを確認しているようです。

あなたは自分で試すことができます:

$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1

これにより、接続されている画面(ディスプレイ)の数が10秒間表示されます。

これが実行されている間、画面/モニターのプラグを抜き差しして、何が起こるか見てください。したがって、小さなBashテスト関数を作成できます。

isVgaConnected() {
    local xRandr=$(xrandr -q)
    [ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
    return 1
}

次のように使用できます:

$ if isVgaConnected; then echo yes; fi

ただし、プラグで変更が発生しない間xrandrは約0.140秒から0.200秒かかり、直前に何かがプラグインまたはアンプラグされた場合は最大0.700秒かかります(注:リソースを食べる人ではないようです)。

編集#1

間違ったことを教えないようにするために、Webとドキュメントを検索しましたが、DBusとScreensについては何も見つかりませんでした。

最後に、2つの異なるウィンドウで実行しましたdbus-monitor --system(オプションで遊んでいます)。

$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done

...モニターのプラグを抜くよりも何度も差し込んだ。だから今私は言うことができます:

  • この構成では、i915ドライバーを使用xrandr -qして、モニターがプラグインされているかどうかを実行する以外に方法はありません。

ただし、他の方法はないように見えるため、注意してください。例えば、xrandr私のGNOMEデスクトップに切り替えるしまうので、この情報を共有しているようだxinerama...自動的に私が走ったときxrandr

いくつかのドキュメント


4

次の行が udevadm monitor

KERNEL[46578.184280] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV  [46578.195887] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)

VGAコネクタにモニターを接続する場合。したがって、これを理解する方法があるかもしれません。


nVidia 9800 GTと独自のドライバーを使用すると、HDMIモニターを接続してもudevadmモニターに何も表示されません。どのハードウェア/ドライバーを使用していますか?
フランクスター14

残念なことに、それは私にとって信頼できる動作しません。モニターをプラグインするとこれらのイベントメッセージが表示される場合があります。
トバイアス

3

なんらかの理由でhotplugルートを使用したくない場合は、inotifywaitを使用してスクリプト内でポーリングしないことも可能です。

#!/ bin / bash

SCREEN_LEFT = DP2
SCREEN_RIGHT = eDP1
START_DELAY = 5

renice +19 $$> / dev / null

$ START_DELAYスリープ

OLD_DUAL = "ダミー"

while [1]; 行う
    DUAL = $(cat / sys / class / drm / card0-DP-2 / status)

    if ["$ OLD_DUAL"!= "$ DUAL"]; それから
        if ["$ DUAL" == "connected"]; それから
            echo「デュアルモニターのセットアップ」
            xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal --below $ SCREEN_LEFT
        他に
            echo「シングルモニターのセットアップ」
            xrandr --auto
        fi

        OLD_DUAL = "$ DUAL"
    fi

    inotifywait -q -e close / sys / class / drm / card0-DP-2 / status> / dev / null
やった

末尾の&を忘れずに、.xsessionrcから呼び出すのが最適です。xrandrでポーリングすると、新しいラップトップで深刻なユーザビリティの問題が発生しました(マウスは定期的に停止します)。


私はあなたがinotifyを使用できるとは思っていなかったでしょうし/procinotifywait -q -e close /sys/class/drm/card0-DP-2/status 実際に私のシステムでDP-2を切断しても終了しませんでした
-nhed

3

私はsrandrdの使用にこだわった。Xイベントを監視し、ディスプレイが接続または切断されるとスクリプトをトリガーします。


0

明らかに何かがあるはずです!:) / sysファイルシステムは、使用可能なハードウェアをユーザースペースに通知するため、ユーザースペースツール(udevやmdevなど)は、現在使用可能なハードウェアを表すデバイスノードを「/ dev」ディレクトリに動的に追加できます。Linuxは、/ sbin / hotplugとnetlinkの2つのホットプラグインターフェイスを提供します。

次のファイルに小さなCデモがあります。 http://www.kernel.org/doc/pending/hotplug.txt


0

現在、Linux上のシステム/アプリケーションソフトウェアのほとんどは、相互に通信するためにいくつかのipc技術を使用しています。D-Busは現在GNOMEアプリケーションで主に使用されており、役立つ可能性があります。

Linux Journal:

D-BUSを使用すると、システムを介したイベントまたは信号の送信が容易になり、システム内のさまざまなコンポーネントが通信し、最終的にはより統合しやすくなります。たとえば、Bluetoothデーモンは、音楽プレーヤーが傍受できる着信コール信号を送信し、通話が終了するまで音量をミュートすることができます。

wiki:

D-Busは、システムデーモン(「新しいハードウェアデバイスの追加」や「プリンターキューの変更」など)とユーザーごとのログインセッションデーモン(ユーザーアプリケーション間の一般的なプロセス間通信のニーズ)の両方を提供します。

このためのPythonライブラリもあり、ubuntuは最近「zeitgeist」と呼ばれるこの機能を使用しました。


-6

グラフィカルに、モニターがで認識されるかどうかを確認Monitorできます。これは、Ubuntu、Fedora、およびその他(このような場所)で見つけることができることを知っています。

システム/設定/モニター

また、必要なモニターのオン/オフを切り替えたり、両方を同時に使用したり、両方のモニターまたは独立したモニターで画像を複製したりできます。


2
彼は、モニターがプラグイン/アンプラグされたときにトリガーされるイベントを要求しました
Michael Mrozek

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.