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

二,遇到的問題
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;
}