2015-03-02 28 views
7

Chcę zamknąć system Embedded Linux po naciśnięciu przycisku zamykania w interfejsie użytkownika. Wiem, że mogę to zrobić z wezwaniem do system:Jak zamknąć Linuksa za pomocą C++ lub Qt bez wywoływania "system()"?

system("shutdown -P now"); 

Ref: Link

Ale wiedząc, że za pomocą system nie jest zalecane, I'ld się dowiedzieć czy istnieje inny sposób w C++ zrobić to (jeśli istnieje również specjalny sposób, aby to zrobić za pomocą Qt, ja też lubię to wiedzieć, chociaż ważniejsza jest ogólna metoda C++).

+2

Dlaczego 'System()' nie rozmyślny? – cmannett85

+1

Przeczytaj o [** DBus **] (http://dbus.freedesktop.org/doc/dbus-tutorial.html). BTW, myślę, że istnieje api 'QDBus'. –

+1

@ cmannett85 z bardzo prostego powodu, jeśli OP używa Qt, oznacza to, że wymagałoby to uprawnień roota w aplikacji GUI, naprawdę zły pomysł. Wywoływanie programów z 'system()' prawie zawsze stanowi problem bezpieczeństwa. –

Odpowiedz

13

W systemie Linux można wywołać wywołanie systemowe restart do poweroff, zatrzymania lub restartu. Poniższy fragment kodu pokazuje jak poweroff maszynę, ale należy pamiętać, że będzie to oczywiście tylko pracować na Linuksie:

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

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

Oczywiście, trzeba będzie wystarczających uprawnień, aby skorzystać z tej syscall.

+0

Po to jest dbus, choć skoro jest to wbudowany system, nie wiem, czy dbus jest używany, może być. –

+0

@iharob Rzeczywiście, możesz również użyć DBus do rozmowy z ConsoleKit lub UPower, jeśli są zainstalowane. Nie spodziewałbym się jednak, że wszystkie systemy wbudowane będą je uruchamiały. – tux3

+0

Czy to przestanie poprawnie uruchamiać usługi systemowe, ponieważ działa 'system (restart)? –

1

Jeśli problem jest to, że układ myślisz() nie jest bezpieczna, można użyć

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

wtedy można mieć pewność, że używasz funkcji zamykania prawo.

+1

O ile pamiętam na moim odczyty na 'system()', powody, dla których nie jest zalecane, wykraczają daleko poza "używanie właściwej funkcji wyłączania" :) Ale dzięki! – Momergil

2

Qt sposobem jest użycie QProcess uruchomić polecenie shutdown:

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

Dzięki! Mogę skończyć używanie tego, ponieważ nie mogę znaleźć pliku nagłówka zawierającego 'reboot': x (brak strony pomocy zawierającej' man' mówi, że \ o /) – Momergil

+0

Er, to prawie to samo co 'system()' - w szczególności polecenie jest analizowane przez powłokę. Jednak inne 'QProcess :: startDetached()', które akceptuje argumenty 'QStringList', pozwala uniknąć niektórych problemów. –

6

Pod glibc musisz:

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

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

Ponownie, jak zawsze, trzeba być uruchomione z wystarczającymi przywilejami.

4

Jeśli system nie Systemd, a następnie można użyć logind funkcjonalność poprzez D-Bus. Qt rozwiązanie jest następujące (tylko sprawdzone):

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; 
} 

także możliwość istnieje potrzeba, aby dodać plik /etc/polkit-1/localauthority/50-local.d/10-enable-shutdown.pkla stłumić interaktywną wymóg uwierzytelniania:

[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

Czy ktoś naprawdę używa systemd w systemie wbudowanym? * Shudder. * –

+0

@TobySpeight me. Ale mój system wbudowany jest wystarczająco gruby, aby uruchomić Ubuntu Server i graficzną aplikację z maksymalną pamięcią RAM = ~ 1,5 GB i VRAM = ~ 2 GB. – Orient

+0

Sądzę, że mamy różne oczekiwania co do tego, co jest "osadzone", a następnie! –