QT按鈕socket遠程控制opengl模型(4)--Apple的學(xué)習(xí)筆記

QT按鈕socket遠程控制opengl模型(3)驗證功能通過后,
Linux Server端采用進程IPC通信
。子進程為opengl的顯示。比起多線程,多進程需要處理下進程同步關(guān)閉及僵尸進程。代碼工程依然更新到我的碼云

一,進程設(shè)計

進程IPC通信.png

二,遇到的問題

1.vscode無法調(diào)試多進程

解決方案:
launch.json添加:
"setupCommands": [
{"text": "-gdb-set follow-fork-mode child"}
]

2.linux消息隊列msgrcv收不到消息的問題

解決方案:沒有用man來仔細看msgrcv的函數(shù),網(wǎng)上直接搜索了下,就找到了答案。msgrcv的第一個對象需要使用long,之前32位機上我用int測試通過,現(xiàn)在機器為64bit系統(tǒng),所以long和int的字節(jié)數(shù)量就不是4字節(jié)了,64bit機器的long為8個字節(jié),所以msgrcv一直無法接收到數(shù)據(jù)。修改傳入?yún)?shù)的結(jié)構(gòu)第一個對象為long型,驗證通過。

2.比起多線程,需要關(guān)注同步2個進程的退出

由于Linux Server端窗口關(guān)閉后,主進程socket依然在和win10的client通信。所以opengl窗口關(guān)閉后,需要讓server進程也關(guān)閉。
查了資料,其實進程間算是平等的。
僵尸進程就是指:一個進程執(zhí)行了exit系統(tǒng)調(diào)用退出,而其父進程并沒有為它收尸(調(diào)用wait或waitpid來獲得它的結(jié)束狀態(tài))的進程。
任何一個子進程(init除外)在exit后并非馬上就消失,而是留下一個稱外僵尸進程的數(shù)據(jù)結(jié)構(gòu),等待父進程處理。這是每個子進程都必需經(jīng)歷的階段。另外子進程退出的時候會向其父進程發(fā)送一個SIGCHLD信號。

進程間?;罘桨缚梢酝ㄟ^消息互發(fā),若檢測到子進程不發(fā)消息給父進程,則可以關(guān)閉子進程,再關(guān)閉父進程。
解決方案:由于我是socket讀寫,有阻塞,所以我通過在SIGCHLD通知函數(shù)中直接調(diào)用exit(0)進行強制退出。

三,main.cpp代碼

#include "socket.h"
#include "showgl.h"
#include "ipc.h"

void handler(int sig)
{
    pid_t pid;
    while((pid=waitpid(-1,NULL,WNOHANG))>0)
    {
        printf("wait child is sucessful\n");
        exit(0); //kill father pid
    }
    printf("child is quit\n");
}

int main(int argc, char **argv)
{
    int ret = E_NOK;
    int keydata = 0;
    signal(SIGCHLD,handler);
    /* server operations */
    baseServer *pServer = new baseServer();
    pServer->socketCreate(AF_INET, SOCKET_TYPE, INADDR_ANY, PORT_ID, baseSocket::E_SERVER);
    pServer->socketBind();
    pServer->socketListen(2);
    MYmsg * pMymsg = new MYmsg();
    pMymsg->CreateMsg();
    /* task process */
    ServerHandler *pServerTask = new ServerHandler(pMymsg);
    /* create task for socket to send heartbeat */
    std::thread taskSendHeart(&ServerHandler::sendHeart, pServerTask, pServer);

    
/* create task for opengl to display 3D */
#if (USEFORK == true)
    pid_t id = fork();
    std::cout << "pid=" << id << std::endl;

    if (id < 0)
    {
        std::cout << "fork error" << std::endl;
        exit(0);
    }
    else if (id == 0) //child read
    {
        ShowOpengl *pShowTask = new ShowOpengl();
        pShowTask->glHandler(pMymsg);
        delete pShowTask;
        exit(0);
    }
    else
#else
    ShowOpengl *pShowTask = new ShowOpengl();
    std::thread taskOpengl(&ShowOpengl::glHandler, pShowTask, pServerTask);
#endif
    {//father
        std::cout << "start server\n"; // for debug code
        while (1)
        {
            /* wait client signal to connect */
            ret = pServer->socketAccept();
            std::cout << "h\n"; // for debug code

            /* create task for socket to receive key command */
            std::thread taskRec(&ServerHandler::readinfo, pServerTask, pServer);
            taskRec.detach();

            if (ret == E_OK)
            {
                std::cout << "connect success" << std::endl;
            }
        }
    }
    /* close socket */
    pServer->socketDisconnect(pServer->getConnectfd());
    taskSendHeart.join();
#if (USEFORK == true)
#else
    taskOpengl.join();
    delete pShowTask;
#endif
    delete pServerTask;
    delete pServer;
    pMymsg->delMsg();
    delete pMymsg;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容