簡體   English   中英

從C ++程序啟動可執行文件並繼續

[英]Start an executable from C++ program & continue

我有一個用C ++編寫的程序,旨在在Linux OS上運行。 忽略程序的大部分,可以歸結為這一點-在一段時間后,它會啟動X個可執行文件(為簡單起見,讓我們使用5秒鍾)。

目前,我正在使用system(path/to/executable/executable_name)來實際啟動可執行文件,並且對於啟動可執行文件而言,該方法工作得很好。

我還嘗試維護每個可執行文件的狀態(為簡便起見,再次讓我們說狀態是“ UP”或“ DOWN”(正在運行或未運行))。 我已經能夠完成這個......有點......

備份一點點,當我的程序被告知啟動可執行文件時,邏輯看起來像這樣:

pid = fork()
if (pid < 0) exit 0; //fork failed
if (pid == 0) {
   system(path/to/executable/executable_name)
   set executable's status to DOWN
} else {
   verify executable started
   set executable's status to UP
}

這就是我的問題。 fork()導致產生一個子進程,這是我認為我需要的,以便原始進程繼續啟動其他可執行文件。 我不想等待可執行文件停止以啟動另一個。

但是,可執行文件在另一個子進程中啟動...與父進程分開...如果我嘗試在系統返回時在子進程中將可執行文件的狀態設置為DOWN,則父進程對此一無所知。 ..

我對我可能需要做的事情有一些想法:

  • 使用線程而不是fork:創建一個新線程來調用系統,但是父/主線程是否知道新線程改變了可執行文件的狀態?
  • 使用fork和exec:但是我不確定這會比我已經擁有的更好(我已經閱讀了fork和exec的手冊頁,但是我想我仍然對如何最好地利用exec有點模糊)

有什么建議么?

編輯1我認為我最好為邏輯提供更多的上下文:

void startAll() {
    for each 'executable'
    call startExecutable(executable_name)
}

...

void startExecutable (executable_name) {
    pid = fork()
    if (pid < 0) exit 0; //fork failed
    if (pid == 0) {
        system(path/to/executable/executable_name)
        set executable's status to DOWN
        exit (1); <-- this is because once the child process's system returns, I don't want it to return to the above loop and start starting executables
    } else {
        verify executable started
        set executable's status to UP
    }
}

編輯2如開頭所述,這是假設一個簡化的設置(如果你願意,第一次運行)。 該計划不僅要處理“ UP”或“ DOWN”狀態,還要處理第三個狀態,以處理向程序已啟動的可執行文件發送消息-“ STANDBY”。 我最初離開這篇文章是為了避免使解釋復雜化,但我現在看到包含它是不完美的。

您需要了解fork時到底發生了什么。 你正在做的是創建一個子進程,它是分叉過程的精確克隆。 當前在內存中的所有變量都被精確復制,並且子進程可以訪問所有這些變量的所有副本。

但它們是副本,因此您已經注意到,fork和exec / system本身並不處理進程間通信(IPC)。 在其中一個進程中設置內存值不會在任何其他進程(包括其父進程)中更改該變量,因為內存空間不同。

此外, systemexec非常相似,但是對文件描述符和執行環境的控制要少得多。 您實際上已經在執行fork和exec,這是您應該做的。

當你正確分叉時(就像在你的例子中那樣),你現在有兩個進程,而且沒有一個正在等待另一個進程 - 它們只是在完全不同的代碼路徑中運行。 你基本上想要的是讓父母什么也不做,只是坐在那里等待新的節目開放,偶爾檢查孩子的狀態,而孩子們只要他們想要的話就跑步和玩耍。

有IPC解決方案,例如管道和消息FIFO隊列,但是在您的情況下這太過分了。 就您而言,您只是在尋找流程管理。 父母被賦予孩子的身份。 保存並使用。 您可以調用waitpid等待孩子結束,但您不希望這樣。 您只希望父母檢查孩子的狀態。 一種方法是檢查if kill(childPid,0) == 0 如果不是,則表明該pid已退出,即不再運行。 您也可以檢查/proc/childPid以獲取各種信息。

如果您的狀態不如隱含的問題那么簡單,那么您將需要在分叉和執行后查看管道。 否則,您只需要進行過程監視即可。

基於EDIT 2 ,您仍然處於流程管理領域,而不是IPC。 kill命令將信號發送到進程(如果該命令為非0)。 你正在尋找的是讓父母kill(childPid, SIGTSTP) 在子方面,您只需要使用signal命令創建一個信號處理程序。 在許多其他參考資料中,請參閱http://www.yolinux.com/TUTORIALS/C++Signals.html 基本上,您需要:

void sigTempStopHandler(int signum) { /* ... */ }
signal(SIGTSTP, sigTempStopHandler);

在子代碼中執行。 父級當然會知道何時發送此狀態,因此可以更改狀態。 必要時,您可以使用其他信號來恢復。

何時傳遞信號與信號:

管道是您可以使用的最強大的IPC - 它允許您將任意數量的數據從一個進程發送到另一個進程,並且可以在您想要的任何方向上。 如果你希望你的父母給孩子發送“你是一個非常壞的男孩”,它可以,並且孩子可以發送“但我有一天會選擇你的療養院”給父母。 (可以輕松地將任何數據(文本或二進制)從一個進程傳遞到另一個進程-包括要序列化的對象,或者如果對象的原始數據不依賴於內存(例如int),則可以僅傳遞這些數據。)

到目前為止,您所描述的是從父級向子級發送簡單的命令結構,並且kill是完美的。 孩子可以發送信號幾乎一樣容易 - 除了它需要知道父母的pid才能做到這一點。 (不難做-在派生之前,保存pid: int pid = getPid();現在孩子知道了父對象。)信號沒有數據,它們只是非常原始的事件,但到目前為止,聽起來像是所有事件您正在尋找。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM