system 調用 Qt 程序的問題

system 調用 Qt 程序的問題

在公司做了一個嵌入式系統的引導程序,進程在系統開始後自啓動(這裏使用的是 rc.local 添加啓動項的方法),隨後按照相應的順序依次啓動相應的程序,之前一直沒有出現什麼問題,直到增加了一個啓動 Qt 程序,並監控程序狀態的需求後,出現了一些無法解釋的問題。

編寫代碼的過程

  • 第一個需求:進程中調用一個 Qt 程序。

這個代碼很簡單,爲了省事,簡單使用了 system() 函數。

    system("QtApplication -qws");
  • 第二個需求:需要獲取 QtApplication 的返回值。

system 函數的執行過程分爲三個步驟:
1. 創建一個子進程,主要是 fork() 等過程。
2. 調用 /bin/sh 拉起 shell 腳本。
3. 執行相應的 shell 腳本,waitpid()。

因此,system 的返回值(status)囊括了以上三個步驟的結果:
1. 如果調用子進程失敗,或者 waitpid() 返回除了 EINTR 之外的錯誤,system 返回 -1;
2. 如果 shell 拉起失敗或未正常執行結束(只要能夠調用到 /bin/sh,並且執行shell過程中沒有被其他信號異常中斷,都算正常結束),原因值被寫入到status的低8~15比特位中。
系統提供了宏:WIFEXITED(status) 來判斷 shell 的執行結果。如果 WIFEXITED(status) 爲真,則說明正常結束。
3. 如果 shell 腳本正常執行結束,將 shell 返回值填到 status 的低8~15比特位中。
同樣系統提供了宏:WEXITSTATUS(status) 來獲取相應腳本的執行結果。

一個簡單的執行代碼如下, 因爲程序需要執行一段時間,所以添加了一個輪詢:

int system_call()
{
    int status = 9;
    status = system("QtApplication -qws");
    for(int i = 0; i < 6000; i++)
    {
        if(status != 9)
        {
            if( -1 == status) //status == -1, 子進程創建失敗
            {
                printf("system error!"); 
                return -1;
            }
            else
            {
                if(WIFEXITED(status)) //WIFEXITED(status) 爲真,QtApplication 成功執行
                {
                    if(0 == WEXITSTATUS(status))
                    {
                        printf("QtApplication successfully.\n"); //Qt 程序執行成功
                        return 0;
                    }
                    else
                    {
                        printf("QtApplication failed, exit code: [%d]\n", WEXITSTATUS(status));//Qt 程序執行失敗,獲取失敗返回值。
                        return -1;
                    }
                }
                else
                {
                    printf("exit status = [%d]\n", WEXITSTATUS(status)); //WIFEXITED(status) 不爲真,shell 調用失敗。
                    return -1;
                }
            }
        }
        usleep(100);
    }
    return -1;
}

出現的問題

編寫完這個代碼後簡單的執行,調試,沒有發現什麼問題,所以開始進行測試,結果出現一個很奇怪的現象:
當 Qt 程序沒有執行完成的時候,system 返回了程序的返回值,並打印了以下的語句:exit status = [0]

更爲奇怪的是同樣的問題,當手動執行 system_call 的時候,並不會出現這樣的問題。

爲什麼會出現這樣的問題?

經過對系統代碼的分析,發現,在系統啓動時啓動一個撥號程序,而這個程序在系統啓動大概200ms的時候殺死了所有的 sh 程序。

問題的解決

因爲撥號程序不能更改,所以只能先通過 exec 的方法調用程序,畢竟system()函數用起來很容易出錯!!!

於是,嘗試了使用 exec 直接執行的方式來調用子程序,代碼如下:

int system_call()
{
    pid_t pid, ret;
    int status;
    if((pid = fork()) < 0)
    {
        printf("Fork Failed!");
        return -1;
    }
    else if(pid == 0)
    {
        if((status = execlp("QtApplication", "QtApplication", "-qws", NULL)) < 0)
        {
            printf("EXEC Failed!");
        }
    }
    else
    {
        for(int i = 0; i < 6000; i++)
        {
            ret = waitpid(pid, &status, WNOHANG);
            if(ret == pid)
            {
                if(WIFEXITED(status))
                {
                    if(0 == WEXITSTATUS(status))
                    {
                        printf("QtApplication successful", 3);
                        return 0;
                    }
                    else
                    {
                        printf("tcu_update failed with CODE[%d]",  WEXITSTATUS(status));
                        return -1;
                    }
                }
                else
                {
                    printf("tcu_update start failed with CODE[%d]",  WEXITSTATUS(status));
                    return -2;
                }

            }
            usleep(100000);
        }
        return -2;
    }

}

參考:

【C/C++】Linux下system()函數引發的錯誤)
【C/C++】Linux下system()函數引發的錯誤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章