2015-03-02 84 views
7

我想在用戶界面上按下關閉按鈕時關閉嵌入式Linux。我知道我可以用電話做它01​​:如何在不調用「system()」的情況下使用C++或Qt關閉Linux?

system("shutdown -P now"); 

編號:Link

但我們知道,使用system不建議,I'ld想知道如果在C++做的另一種方式這個(如果還有一個使用Qt的特定方法,我也想知道它,儘管一般的C++方法更重要)。

+2

爲什麼'系統()'不建議? – cmannett85 2015-03-02 14:45:16

+1

閱讀關於[** DBus **](http://dbus.freedesktop.org/doc/dbus-tutorial.html)。順便說一句,我覺得有一個'QDBus' api。 – 2015-03-02 14:46:15

+1

@ cmannett85出於一個非常簡單的原因,如果OP使用Qt,這意味着它將需要GUI應用程序中的root權限,這真是個壞主意。用'system()'調用程序幾乎總是代表一個安全問題。 – 2015-03-02 14:47:10

回答

13

在Linux上,您可以調用reboot系統調用來關閉,暫停或重新啓動。 下面的代碼片段展示瞭如何執行poweroff到一臺機器,但要注意,它當然只在Linux上工作:

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

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

當然,你需要足夠的權限來使用這個系統調用。

+0

這是dbus的用途,雖然因爲它是一個嵌入式系統,所以我不知道是否使用了dbus,它可能是。 – 2015-03-02 14:55:41

+0

@iharob事實上,如果安裝它們,您也可以使用DBus與ConsoleKit或UPower進行通信。但我不希望所有嵌入式系統都能讓它們運行。 – tux3 2015-03-02 14:58:16

+0

這是否會像system(reboot)一樣正常運行systemd服務? – 2017-02-01 09:01:31

1

如果你的問題是,您認爲系統()不是很安全,你可以使用

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

那麼你可以確保你使用正確的關機功能。

+1

據我在系統()上的讀物記得,爲什麼它不被推薦遠遠超出「使用正確的關閉功能」:)但是,謝謝! – Momergil 2015-03-02 16:38:52

2

Qt的方式是使用QProcess運行shutdown命令:

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

謝謝!我可能最終會使用這個,因爲我找不到包含'reboot'的頭文件:x(沒有幫助頁面包括'man'告訴\ o /) – Momergil 2015-03-02 17:31:40

+0

呃,這與'system()'幾乎相同 - 特別是,命令由shell解析。然而,接受參數'QStringList'的另一個'QProcess :: startDetached()'避免了一些問題。 – 2018-01-12 10:47:56

6

下的glibc,你需要:

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

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

再次,一如既往,你需要運行具有足夠的特權。

4

如果您的系統已經systemd,那麼你可以通過d總線使用logind功能。 的Qt解決方案如下(只測試):

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

也可能有必要添加文件/etc/polkit-1/localauthority/50-local.d/10-enable-shutdown.pkla打壓交互認證要求:

[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

有人真的在嵌入式系統上使用systemd嗎? * Shudder。* – 2018-01-12 10:44:28

+0

@TobySpeight me。但是我的嵌入式系統足夠運行Ubuntu Server和圖形應用程序,峯值RAM =〜1.5GB,VRAM =〜2GB。 – Orient 2018-01-12 11:58:36

+0

我想我們對「嵌入」有什麼不同的期望,那麼! – 2018-01-12 12:06:01

相關問題