2015-03-02 2 views
7

Ich möchte ein Embedded Linux herunterfahren, wenn eine Schließen-Schaltfläche auf der Benutzeroberfläche gedrückt wird. Ich weiß, dass ich es mit einem Aufruf an system tun können:Wie Linux mit C++ oder Qt ohne Aufruf von "system()" heruntergefahren wird?

system("shutdown -P now"); 

Ref: Link

Aber zu wissen, dass system Verwendung wird nicht empfohlen, I'ld gerne wissen, ob es eine andere Art und Weise in C++ zu tun dies (wenn es auch einen bestimmten Weg gibt, dies mit Qt zu tun, möchte ich es auch wissen, obwohl eine allgemeine C++ - Methode wichtiger ist).

+2

Warum ist 'System()' nicht beraten? – cmannett85

+1

Lesen Sie über [** DBus **] (http://dbus.freedesktop.org/doc/dbus-tutorial.html). BTW, da ist eine 'QDBus'-API, denke ich. –

+1

@ cmannett85 aus einem sehr einfachen Grund, wenn das OP Qt verwendet bedeutet es, dass Root-Berechtigungen innerhalb einer GUI-Anwendung erfordern würde, wirklich schlechte Idee. Das Aufrufen von Programmen mit 'system()' stellt fast immer ein Sicherheitsproblem dar. –

Antwort

13

Unter Linux können Sie den Neustart-Systemaufruf zum Ausschalten, Anhalten oder Neustarten aufrufen. Der folgende Ausschnitt zeigt, wie eine Maschine poweroff, aber beachten Sie, dass es natürlich nur unter Linux:

#include <unistd.h> 
#include <linux/reboot.h> 

int main() { 
    reboot(LINUX_REBOOT_MAGIC1, 
      LINUX_REBOOT_MAGIC2, 
      LINUX_REBOOT_CMD_POWER_OFF, 0); 
} 

Natürlich werden Sie ausreichende Berechtigungen benötigen diese syscall zu verwenden.

+0

Dafür ist dbus da, obwohl es ein eingebettetes System ist, weiß ich nicht ob dbus benutzt wird, könnte es sein. –

+0

@iharob Sie könnten DBus auch verwenden, um mit ConsoleKit oder UPower zu sprechen, wenn sie installiert sind. Ich würde jedoch nicht erwarten, dass alle Embedded-Systeme sie ausführen. – tux3

+0

Hört das auf, systemd-Dienste korrekt auszuführen, während 'system (reboot)' das tut? –

1

Wenn Ihr Problem ist, dass Sie System denken() nicht sicher ist, können Sie

system("/bin/sh shutdown -P now"); 

verwenden, dann können Sie sicher, dass Sie die richtige Abschaltfunktion verwenden.

+1

Soweit ich mich an meine Lesungen auf 'system()' erinnere, gehen die Gründe, warum es nicht empfohlen wird, weit über "die richtige Abschaltfunktion" hinaus :) :) Aber danke! – Momergil

2

Die Qt Weg ist QProcess zu verwenden, um den Befehl zum Herunterfahren auszuführen:

QProcess process; 
process.startDetached("shutdown -P now"); 
+0

Danke! Ich kann das am Ende verwenden, da ich nicht finden kann, welche Header-Datei "reboot" enthält: x (keine Hilfeseite einschließlich 'man' sagt das \ o /) – Momergil

+0

Äh, das ist ziemlich genau dasselbe wie' system() '- Insbesondere wird der Befehl von einer Shell geparst. Das andere 'QProcess :: startDetached()', das eine 'QStringList' von Argumenten akzeptiert, vermeidet jedoch einige der Probleme. –

6

Unter glibc werden Sie brauchen:

#include <unistd.h> 
#include <linux/reboot.h> 
#include <sys/reboot.h> 

int main() { 
    sync(); 
    reboot(LINUX_REBOOT_CMD_POWER_OFF); 
} 

Wieder, wie immer, die Sie benötigen zu laufen mit ausreichenden Privilegien.

4

Wenn Ihr System haben systemd, dann können Sie logind Funktionalität über D-Bus verwenden. Qt Lösung ist die folgende (nur getestet):

QDBusInterface logind{"org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus()}; 
const auto message = logind.callWithArgumentList(QDBus::Block, "CanPowerOff", {}); 
QDBusPendingReply<QString> canPowerOff = message; 
Q_ASSERT(canPowerOff.isFinished()); 
if (canPowerOff.isError()) { 
    const auto error = canPowerOff.error(); 
    qWarning().noquote() 
      << QDBusInterface::tr("Asynchronous call finished with error: %1 (%2)") 
       .arg(error.name(), error.message()); 
    return EXIT_FAILURE; 
} 
if (canPowerOff.value() == "yes") { 
    QDBusPendingReply<> powerOff = logind.callWithArgumentList(QDBus::Block, "PowerOff", {true, }); 
    Q_ASSERT(powerOff.isFinished()); 
    if (powerOff.isError()) { 
     const auto error = powerOff.error(); 
     qWarning().noquote() 
       << QDBusInterface::tr("Asynchronous call finished with error: %1 (%2)") 
        .arg(error.name(), error.message()); 
     return EXIT_FAILURE; 
    } 
} else { 
    qCritical().noquote() 
      << QCoreApplication::translate("poweroff", "Can't power off: CanPowerOff() result is %1") 
       .arg(canPowerOff.value()); 
    return EXIT_FAILURE; 
} 

auch möglich, dass es notwendig ist, eine Datei /etc/polkit-1/localauthority/50-local.d/10-enable-shutdown.pkla zu unterdrücken interaktive Authentifizierung Anforderung hinzuzufügen:

[Enable shoutdown for users] 
Identity=unix-group:users 
Action=org.freedesktop.login1;org.freedesktop.login1.power-off;org.freedesktop.login1.power-off-ignore-inhibit;org.freedesktop.login1.power-off-multiple-sessions 
ResultAny=yes 
ResultInactive=yes 
ResultActive=yes 
+0

Verwendet wirklich jemand Systemd auf einem eingebetteten System? * Shudder. * –

+0

@TobySpeight mich. Aber mein Embedded-System ist fett genug, um Ubuntu Server und grafische Anwendungen mit Spitzen-RAM = ~ 1,5 GB und VRAM = ~ 2 GB zu betreiben. – Orient

+0

Ich denke, wir haben unterschiedliche Erwartungen, was "eingebettet" ist, dann! –

Verwandte Themen