Wie kann ich erkennen, ob ein Monitor angeschlossen oder nicht angeschlossen ist?

53

Gibt es ein Ereignis, das ausgelöst wird, wenn ich einen externen Monitor an den DisplayPort meines Laptops anschließe oder ausbaue? ACPID und UDEV reagieren überhaupt nicht.

Ich verwende integrierte Grafiken auf einem Intel-Chip. Hier ist eine ähnliche Diskussion, die bereits ein paar Jahre alt ist.

Ich möchte kein Polling verwenden, benötige jedoch eine Konfiguration, mit der die Anzeigeeinstellungen automatisch festgelegt werden, je nachdem, ob die Anzeige angeschlossen ist.

Janoliver
quelle
4
Es kann mit udev gemacht werden. Was ist deine Kernel-Version? Verwenden Sie KMS (Kernelmoduseinstellung)?
Andy
Danke für die Antwort. Ich bin mir bei KMS nicht sicher, aber wie ich in der Frage sagte, sendet udev keine Ereignisse. ( udevadm monitor - property reagiert überhaupt nicht)
janoliver
@Andy: Als dies das letzte Mal auftauchte , schienen die meisten Systeme abzufragen. Wenn Sie einen Weg gefunden haben, ein udev-Ereignis auszulösen, können Sie diese Frage beantworten?
Gilles 'SO- hör auf böse zu sein'
1
Ich habe es endlich zum Laufen gebracht, indem ich i915 als Kernelmodul geladen habe.
Janoliver
3
Sie können xrandr oder disper verwenden, um festzustellen, ob ein externer Monitor angeschlossen ist. Github.com/wertarbyte/autorandr zeigt Ihnen, wie Sie diese verwenden. Xrandr / disper unterstützt Ihre Grafikkarte möglicherweise nicht.
Nummer

Antworten:

13

HINWEIS: Dies wurde auf einem Laptop mit einer i915-Grafikkarte getestet.


Hintergrund

HINWEIS: Wenn ein neuer Bildschirm angeschlossen wird, wird kein Ereignis an den Host gesendet. Dies ist auch nach meiner letzten Bearbeitung der Fall. Der einzige Weg ist das Polling. Wir versuchen, sie so effizient wie möglich zu gestalten ...

EDIT # 3

Endlich gibt es eine bessere Lösung (über ACPI):

Es gibt noch keine Veranstaltung, aber ACPI scheint effizienter zu sein, als sich xrandrzu erkundigen. (Hinweis: Hierfür müssen ACPI-Kernelmodule geladen sein, es sind jedoch keine Root-Berechtigungen erforderlich.)

Meine endgültige Lösung (mit bash):

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

Nun ein Test:

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

Es ist eingesteckt, also ziehe ich es jetzt heraus:

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

HINWEIS: ${1:+*-1+1} eine Genehmigung boolean Argument: Wenn etwas vorhanden ist , würde Antwort invertiert werden: ( crtState >> 4 ) * -1 + 1.

und das letzte Drehbuch:

#!/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

WARNUNGEN: Leichter als xrandr, aber nicht unwichtig mit einer Verzögerung von weniger als 0,02 Sekunden. Das Bash-Skript springt an die Spitze des Ressourcenfresser-Prozesses ( top)!

Während dies ~ 0,001 Sek. Kostet:

$ time read -a </proc/stat crtStat

Dies erfordert ~ 0,030 Sekunden:

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

Das ist groß! Also je nachdem, was Sie brauchen, delaykönnte einigermaßen zwischen 0.5und gesetzt werden 2.

EDIT # 2

Ich habe endlich etwas gefunden, mit diesem:

Wichtiger Hinweis: Das Spielen mit /procund die /sysEinträge können Ihr System beschädigen !!! Versuchen Sie Folgendes nicht auf Produktionssystemen.

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

... nach einigem Reinigen von unerwünschten Einträgen:

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

Ich konnte Folgendes lesen:

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

Wenn ich das Monitorkabel einstecke, ausziehe und wieder einstecke.

Ursprüngliche Antwort

Wenn die Konfiguration abgefragt wird (läuft system/preferences/monitoroder xrandr), führen Grafikkarten eine Art Scan durch , so dass beim Ausführen xrandr -qdie Informationen angezeigt werden, der Status jedoch abgefragt werden muss .

Ich habe alle Protokolle (Kernel, Daemon, X usw.) durchsucht und /proc& durchsucht /sys, und es scheint offensichtlich nichts zu geben, das Ihre Anfrage erfüllt.

Ich habe es auch versucht:

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

Nach all dem wird System/Preferences/Monitordas Tool einfach (normalerweise) angezeigt , wenn Sie ausführen, während noch kein neuer Bildschirm eingesteckt oder ausgesteckt wurde. Wenn Sie zuvor einen Bildschirm ein- oder ausgesteckt haben, führen Sie dieses Tool gelegentlich aus, und auf Ihrem Desktop wird eine Art Zurücksetzen oder Aktualisieren ausgeführt (dies gilt auch für den Fall, dass Sie einen Bildschirm ausführen xrandr).

Dies scheint zu bestätigen, dass dieses Tool nach dem xrandrStatus fragt (oder auf die gleiche Weise funktioniert), indem es diesen regelmäßig abruft, beginnend zum Zeitpunkt seiner Ausführung.

Du könntest es selbst versuchen:

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

Dies zeigt für 10 Sekunden an, wie viele Bildschirme (Displays) verbunden sind.

Während dies läuft, stecken Sie Ihren Bildschirm / Monitor ein und / oder aus und schauen, was passiert. So können Sie eine kleine Bash-Testfunktion erstellen:

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

das wäre verwendbar wie in:

$ if isVgaConnected; then echo yes; fi

Aber seien Sie vorsichtig, es xrandrdauert ungefähr 0,140 Sekunden bis 0,200 Sekunden, während sich an den Steckern nichts ändert, und bis zu 0,700 Sekunden, wenn etwas kurz zuvor eingesteckt oder abgezogen wurde ( HINWEIS: Es scheint kein Ressourcenfresser zu sein).

EDIT # 1

Um sicherzustellen, dass ich nichts Falsches unterrichte, habe ich im Web und in den Dokumenten gesucht, aber nichts über DBus und Bildschirme gefunden .

Schließlich habe ich in zwei verschiedenen Fenstern dbus-monitor --system(ich habe auch mit Optionen gespielt) und dem kleinen Skript, das ich geschrieben habe, ausgeführt:

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

... und steckte den Monitor wieder ein, dann steckte er ihn wieder aus. So jetzt könnte ich sagen:

  • In dieser Konfiguration i915 - Treiber verwendet , gibt es keine andere Möglichkeit , als das Laufen xrandr -qzu wissen , ob ein Monitor angeschlossen ist oder nicht.

Aber seien Sie vorsichtig, denn es scheint keine anderen Möglichkeiten zu geben. Zum Beispiel xrandrscheint diese Information zu teilen, so dass mein GNOME-Desktop xineramaautomatisch auf ... umschaltet, wenn ich liefxrandr .

Einige Dokumente

F. Hauri
quelle
4

Die folgenden Zeilen erschienen in 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)

beim Anschließen eines Monitors an den VGA-Anschluss. Es könnte also einen Weg geben, dies herauszufinden.

sebastianwagner
quelle
Mit einem nVidia 9800 GT und proprietären Treibern zeigt der udevadm-Monitor nichts an, wenn ich einen HDMI-Monitor anschließe. Welche Hardware / Treiber verwenden Sie?
Frankster
Schade, dass das bei mir nicht zuverlässig funktioniert. Manchmal erhalte ich diese Ereignismeldungen, wenn ich meinen Monitor anschließe, und manchmal nicht.
Tobias
3

Für diejenigen, die aus irgendeinem Grund den Hotplug-Weg nicht einschlagen möchten, ist es dennoch möglich, in einem Skript nicht mit inotifywait abzufragen:

#! / bin / bash

SCREEN_LEFT = DP2
SCREEN_RIGHT = eDP1
START_DELAY = 5

renice +19 $$> / dev / null

$ START_DELAY schlafen

OLD_DUAL = "Dummy"

während [1]; machen
    DUAL = $ (cat / sys / class / drm / card0-DP-2 / status)

    if ["$ OLD_DUAL"! = "$ DUAL"]; dann
        if ["$ DUAL" == "connected"]; dann
            Echo 'Dual-Monitor-Setup'
            xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal --below $ SCREEN_LEFT
        sonst
            Echo 'Single Monitor Setup'
            xrandr --auto
        fi

        OLD_DUAL = "$ DUAL"
    fi

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

Es wird am besten von Ihrer .xsessionrc aufgerufen, wobei die Endung & nicht vergessen wird. Das Polling mit xrandr führte bei meinem brandneuen Laptop zu schwerwiegenden Usability-Problemen (die Maus kam regelmäßig zum Stillstand).

Balzola
quelle
Ich hätte nicht gedacht, dass Sie inotify auf verwenden können, /procund habe in der inotifywait -q -e close /sys/class/drm/card0-DP-2/status Tat nicht
aufgehört,
3

Ich habe mich an srandrd gehalten . Es überwacht X-Ereignisse und löst Ihr Skript aus, wenn eine Anzeige verbunden oder getrennt wird.

scorpp
quelle
0

Offensichtlich sollte es etwas geben! :) Das / sys-Dateisystem teilt dem Userspace mit, welche Hardware verfügbar ist, sodass Userspace-Tools (wie udev oder mdev) ein "/ dev" -Verzeichnis dynamisch mit Geräteknoten füllen können, die die aktuell verfügbare Hardware darstellen. Linux bietet zwei Hotplug-Schnittstellen: / sbin / hotplug und netlink.

In der folgenden Datei befindet sich eine kleine C-Demo. http://www.kernel.org/doc/pending/hotplug.txt

Roncsak
quelle
0

Heutzutage verwendete die System- / Anwendungssoftware unter Linux zumeist einige IPC-Techniken für die Kommunikation. D-Bus wird jetzt hauptsächlich mit GNOME-Anwendungen verwendet und könnte helfen.

Linux Journal:

D-BUS kann das Senden von Ereignissen oder Signalen durch das System erleichtern, sodass verschiedene Komponenten im System kommunizieren und sich letztendlich besser integrieren können. Ein Bluetooth-Gerät kann beispielsweise ein eingehendes Anrufsignal senden, das Ihr Musikplayer abfangen kann, und die Lautstärke stummschalten, bis der Anruf beendet ist.

wiki:

D-Bus bietet sowohl einen System-Daemon (für Ereignisse wie "Neues Hardwaregerät hinzugefügt" oder "Druckerwarteschlange geändert") als auch einen Daemon für Anmeldesitzungen pro Benutzer (für allgemeine prozessübergreifende Kommunikationsanforderungen zwischen Benutzeranwendungen).

Es gibt sogar eine Python-Bibliothek dafür, und Ubuntu hat kürzlich diese Fähigkeit namens " Zeitgeist " verwendet.

Amir Naghizadeh
quelle
-6

Grafisch kann man sehen, ob der Monitor mit erkannt wird Monitor, ich weiß, dass man dies auf Ubuntu, Fedora und anderen an diesem (oder einem ähnlichen) Ort findet.

System / Einstellungen / Monitor

Und Sie können jeden gewünschten Monitor ein- und ausschalten oder beide gleichzeitig mit doppelten Bildern auf beiden Monitoren oder unabhängigen Monitoren verwenden

Bruce_Warrior
quelle
2
Er fragte nach einem Ereignis, das ausgelöst wird, wenn ein Monitor angeschlossen / entfernt wird
Michael Mrozek
Hast du hier geschaut? stackoverflow.com/questions/5469828/…
Satish