写了一个简单的多进程的框架,其实很简单但是意义却不仅在于此。
一.网上弄够编译通过的这种代码几乎=0,都是象征性的贴几段代码,直接拿下来,编都编译不过。
二.近期打算写一个基于epoll网络模型的服务器框架,前端网络接入全部由框架完成,而收到包之后的业务逻辑交给业务自己完成,这里的业务逻辑的进程数是可以动态调整的,所以用到了fork进程的概念(因为线程对代码编写要求太高)
好了代码如下(在文章末尾会直接放出代码下载,在suse linux 10下编译通过):
/*==============================================
#
# Author: dantezhu – zny2008@gmail.com
#
# QQ : 327775604
#
# Last modified: 2009-11-05 19:30
#
# Filename: forkwork_use.cpp
#
# Description: 多进程的一个框架,大家可以直接使用,已经经过功能测试和压力测试。
# 编译:g++ forkwork_use.cpp -o forkwork_use
# (实际上看过我写的 VIM-一键编译单个源文件 的话,直接按下F5就行了)
#
================================================*/
#include <iostream>
#include <pthread.h>
#include <asm/atomic.h>
#include <string>
#include <vector>
#include <sys/time.h>
#include <asm/atomic.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <map>
using namespace std;
//==============================================
typedef std::pair<pid_t,int> pidPair;
map<pid_t,int> g_MapPids;int DoYourWork(int iIndex);
/**
* @brief 检查子进程情况(不需要改动)
*
* @param bNeedCon true:父进程发现子进程死掉就会重新拉起子进程;
* false:父进程在所有子进程都退出之后也会退出。
*
* @return 0 succ
* else fail
*/
int DetectPids(bool bNeedCon)
{
pid_t pid;
pid_t _n_pid;
int Ret;
for(;;)
{
//会阻塞在这里,等待有子进程退出
pid = waitpid(-1,NULL,0);
if ( pid < 0 )
{
sleep(1);
continue;
}
if(!bNeedCon)//等待结束
{
g_MapPids.erase(pid);
if(g_MapPids.size()==0)
return 0;
}
else//检测拉起
{
if(g_MapPids.count(pid)<=0)
{
sleep(1);
continue;
}
int index=g_MapPids.find(pid)->second;
g_MapPids.erase(pid);
_n_pid = fork();
if(_n_pid<0)
{
sleep(1);
continue;
}
else if ( _n_pid == 0 )
{
printf(“i am child\n”);
g_MapPids.clear();
Ret = DoYourWork(index);
return Ret;
}
else
{
printf(“i am farther,child is %d,index is %d\n”,_n_pid,index);
g_MapPids.insert(pidPair(_n_pid,index));
}
sleep(1);
}
}
return 0;
}
/**
* @brief 执行启动多个子进程的逻辑(不需要改动)
*
* @param forknum 子进程个数
* @param bNeedCon true:父进程发现子进程死掉就会重新拉起子进程;
* false:父进程在所有子进程都退出之后也会退出。
*
* @return 0 succ
* else fail
*/
int ForkWork(int forknum,bool bNeedCon)
{
g_MapPids.clear();
pid_t pid=0;
int Ret;
for(int i=0;i<forknum;++i)
{
pid=fork();
if(pid==-1)
return -1;//err
else if(pid==0)//child
{
//执行
printf(“i am child\n”);
g_MapPids.clear();
Ret = DoYourWork(i);
return Ret;
}
else
{
printf(“i am farther,child is %d,index is %d\n”,pid,i);
g_MapPids.insert(pair<pid_t,int>((pid_t)pid,(int)i));
}
}
printf(“start all pids and start detect\n”);
DetectPids(bNeedCon);
return 0;
}
/**
* @brief 用户需要执行的函数(需要用户实现)
*
* @param iIndex 给这个进程分配一个userId,存储在父进程的pid->userId的映射表里;
* 主要目的是为了实现当子进程自己死掉,父进程可以重新根据map表传入这个userId
*
* @return 0 succ
* else fail
*/
int DoYourWork(int iIndex)
{
//do your ownthing
sleep(5);
return 0;
}
int main(int argc,char ** argv)
{
if(argc < 2)
{
printf(“please input maxforknum needCon(0/1)\n”);
printf(“eg. ./forkwork_use 10 1\n”);
return 0;
}
int iForkNum=atoi(argv[1]);
bool bNeedCon=atoi(argv[2]);
ForkWork(iForkNum,bNeedCon);
}
执行结果如下:
forkwork_use.cpp下载
后续会慢慢开始新框架的编写,欢迎大家提出意见。
王济尧 on #
你好,想问一下这个判断有什么用?
if(g_MapPids.count(pid)<=0)
{
sleep(1);
continue;
}
Reply