下面程序是我以前写过的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);
}