Fork子进程实现业务逻辑代码示例(Linux C)

下面程序是我以前写过的fork子进程处理异步请求的代码段,记录下来,以便备用。

 

int main( int argc , char * argv[ ] )
{
 int iRet;
 int iFetchRetCode=0;
 int iForkNum=0;
 int iForkMax=0;
 int childPid=0;
 int i=0;
 int size = 10; /*设置进程并发数*/
 
 int pRet = 0; /*进程追踪返回值*/
 int s_pids[size];  /*进程号数组*/

 EXEC SQL BEGIN DECLARE SECTION;
  char aczDbName[128];
  
  char traceid[64];             /*跟踪号*/
  char reqtime[32];             /*请求时间*/
  char reqfilename[256];        /*请求文件名*/
  char fileNameFromC[128];
  char trstrInsID[20];
  char reqtxcode[32];
  int iCount = 0;
 EXEC SQL END DECLARE SECTION;


 /* 取数据库名称 */
 iRet = readConfig( "FISP", "DBNAME", aczDbName, 64 );
 if( iRet != 0 ){
  LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "Cannot get the name of FISP DBNAME!", iRet );
  exit( -1 );
 }
 LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "DBNAME is [%s] !\n", aczDbName );

 
 daemon_start( 1 );


 /* 打开数据库 */
 EXEC SQL DATABASE :aczDbName;
 if( sqlca.sqlcode != 0 ){
  LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "Cannot get the DATABASE [%s] ! ERR=[%d]",aczDbName, sqlca.sqlcode );
  return( -8001 );
 }
 EXEC SQL SET LOCK MODE TO WAIT 10;
 if( sqlca.sqlcode != 0 ){
  LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "EXEC SQL SET LOCK MODE TO WAIT 10 [%s] ! ERR=[%d]",aczDbName, sqlca.sqlcode );
  return( -8001 );
 }
 
 /*初始化子进程号变量值*/
 for(i=0; i<size; i++){
   s_pids[i] = 0;
 }
 /* 设置并发进程上限数iForkMax=size, 开始fork子进程异步交易 */
 iForkMax=size;
 iForkNum=0;
 while(1){
   if(iForkNum > 0){
     /*检查子进程是否执行完毕*/
     for(i=0; i<size; i++){
       LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "检查进程是否结束前第[%d]个的进程号的值为[%d]", i, s_pids[i] );
       if(s_pids[i] != 0){
         pRet = waitpid(s_pids[i], NULL, WNOHANG);
         if(pRet == -1){   /*等于-1时说明进程结束*/
           s_pids[i] = 0;
           iForkNum --;
         }
         LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "第[%d]个进程号的waitpid返回状态为[%d]", i, pRet );
       }
       LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "检查进程是否结束后第[%d]个的进程号的值为[%d]", i, s_pids[i] );
     }
   }
   
   /*查询待做异步处理的记录数*/
   EXEC SQL DECLARE asy_record CURSOR WITH HOLD FOR
   SELECT  traceid, reqtime, reqfilename, filenameformC, trstrInsID, txcode FROM test_asydealmsg  WHERE  dealstate="1";
   if( sqlca.sqlcode != 0 ){
     LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "Declare the course error! ERR=[%d]", sqlca.sqlcode);
     EXEC SQL CLOSE asy_record;
     EXEC SQL FREE asy_record;
     sleep(3);
     continue;
   }
   EXEC SQL OPEN asy_record;
   if( sqlca.sqlcode != 0 ){
     LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "Open the cursor error! ERR=[%d]", sqlca.sqlcode );
     EXEC SQL CLOSE asy_record;
     EXEC SQL FREE asy_record;
     sleep(3);
     continue;
   }
   
   while(1){
     LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "当前子进程数量数为 iForkNum=[%d]", iForkNum ); 
     if( iForkNum < iForkMax ){    /*开始用子进程处理异步请求*/
       memset(traceid, 0x00, sizeof(traceid));
       memset(reqtime, 0x00, sizeof(reqtime));
       memset(reqfilename, 0x00, sizeof(reqfilename));
       memset(fileNameFromC, 0x00, sizeof(fileNameFromC));
       memset(trstrInsID, 0x00, sizeof(trstrInsID));
       memset(reqtxcode, 0x00, sizeof(reqtxcode));
       EXEC SQL FETCH asy_record INTO :traceid, :reqtime, :reqfilename, :fileNameFromC, :trstrInsID, :reqtxcode ;
       iFetchRetCode = sqlca.sqlcode;
       if(iFetchRetCode == 0){
         STR_StrTrim( traceid, ' ' );
         STR_StrTrim( reqfilename, ' ' );
         STR_StrTrim( fileNameFromC, ' ' );
         /*将状态更新成处理中*/
         EXEC SQL UPDATE test_asydealmsg set dealstate = '2' where traceid=:traceid and reqtime=:reqtime;
         if( sqlca.sqlcode != 0 ){
           LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "Update dealstate to 2 error! ERR=[%d]", sqlca.sqlcode);
           continue;
         }
    
         childPid = fork();
         if(childPid > 0){  /*主进程*/
           for(i=0; i<size; i++){
             if(s_pids[i] == 0){
               s_pids[i] = childPid;
               LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "第[%d]个位置的进程号的值赋值为[%d]", i, s_pids[i] );
               iForkNum ++;
               break;
             }
           }
         }else if(childPid == 0){    /*子进程*/
           /*在子进程中处理业务逻辑*/
           iRet = DealRecord( traceid, reqtime, reqfilename, fileNameFromC, trstrInsID, reqtxcode );
           if( 0 != iRet ){
             LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "处理跟踪号为[%s%s]的记录失败", reqtime, traceid );
             exit(200);
           }
           LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "处理跟踪号为[%s%s]的记录成功", reqtime, traceid );
           exit(0);
         }else{ /*fork进程失败的处理*/
           LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "fork进程失败!" );
           EXEC SQL UPDATE test_asydealmsg set dealstate = '1' where traceid=:traceid and reqtime=:reqtime;
           if( sqlca.sqlcode != 0 ){
             LOG_NEW(_ERROR_LOG_TYPE_,_RUN_LVL_, "Fork Fail and Update dealstate to 1 error! ERR=[%d]", sqlca.sqlcode);
           }
           continue;
         }
       }else if(iFetchRetCode == 100){
         LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "FETCH the course no record!" );
         break;
       }else{
         LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "FETCH the cursor error! ERR=[%d]", sqlca.sqlcode );
         break;
       } 
     }else{  /*如果超过规定的并发数则 停顿一秒后检查下子进程状态*/
       sleep(1);
       for(i=0; i<size; i++){
         LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "超并发数!检查进程是否结束前第[%d]个的进程号的值为[%d]", i, s_pids[i] );
         if(s_pids[i] != 0){
           pRet = waitpid(s_pids[i], NULL, WNOHANG);
           if(pRet == -1){
             s_pids[i] = 0;
             iForkNum --;
           }
         }
         LOG_NEW(_INFO_LOG_TYPE_,_RUN_LVL_, "超并发数!检查进程是否结束后第[%d]个的进程号的值为[%d]", i, s_pids[i] );
       }
     }
     
   }
   
   EXEC SQL CLOSE asy_record;
   EXEC SQL FREE asy_record;
   
   /*循环处理后sleep三秒 再次轮训*/
   sleep(3);
 }
 
 EXEC SQL CLOSE DATABASE;
 exit (0);
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值