QT按钮socket远程控制opengl模型(3)验证功能通过后,将
Linux Server端采用进程IPC通信。子进程为opengl的显示。比起多线程,多进程需要处理下进程同步关闭及僵尸进程。代码工程依然更新到我的码云
一,进程设计
进程IPC通信.png二,遇到的问题
1.vscode无法调试多进程
解决方案:
launch.json添加:
"setupCommands": [
{"text": "-gdb-set follow-fork-mode child"}
]
2.linux消息队列msgrcv收不到消息的问题
解决方案:没有用man来仔细看msgrcv的函数,网上直接搜索了下,就找到了答案。msgrcv的第一个对象需要使用long,之前32位机上我用int测试通过,现在机器为64bit系统,所以long和int的字节数量就不是4字节了,64bit机器的long为8个字节,所以msgrcv一直无法接收到数据。修改传入参数的结构第一个对象为long型,验证通过。
2.比起多线程,需要关注同步2个进程的退出
由于Linux Server端窗口关闭后,主进程socket依然在和win10的client通信。所以opengl窗口关闭后,需要让server进程也关闭。
查了资料,其实进程间算是平等的。
僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程。
任何一个子进程(init除外)在exit后并非马上就消失,而是留下一个称外僵尸进程的数据结构,等待父进程处理。这是每个子进程都必需经历的阶段。另外子进程退出的时候会向其父进程发送一个SIGCHLD信号。
进程间保活方案可以通过消息互发,若检测到子进程不发消息给父进程,则可以关闭子进程,再关闭父进程。
解决方案:由于我是socket读写,有阻塞,所以我通过在SIGCHLD通知函数中直接调用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;
}
网友评论