|
藍森林 http://www.lslnet.com 2006年6月6日 10:18
寫了個簡單的進程池,大家幫我看看有什麼問題
現在在測試的時候, 子進程不穩定, 有時候,執行到 某個函數時就會莫名其妙的 當掉,
propool.h:
[code]
#ifndef _PROPOOL_H_
#define _PROPOOL_H_
#include <stdio.h>;
#include <stdlib.h>;
#include <memory.h>;
#include <string.h>;
#include <limits.h>;
#include <time.h>;
#include <signal.h>;
#include <fcntl.h>;
#include <dlfcn.h>;
#include <unistd.h>;
#include <errno.h>;
#include <sys/types.h>;
#include <sys/ipc.h>;
#define FILENAME_LEN 128
#define OFF_WAITTIME 10
#define KEY_FILE1 "POOL.shm"
#define KEY_FILE2 "LOCK.sem"
/***************** 定義枚舉 **********************/
typedef enum EnumPoolStatus /* 進程池狀態 */
{
PSTATUS_ON, /* 可用 */
PSTATUS_OFF /* 不可用 */
}EPoolStatus;
typedef enum EnumChildProcStatus /* 子進程狀態 */
{
CSTATUS_ACT, /* 忙碌 */
CSTATUS_IDLE /* 空閒 */
}EChildProcStatus;
/***************** 定義結構 **********************/
/* 進程池結構*/
typedef struct StruPool
{
pid_t iPid; /*進程號 */
long lRate; /*子進程使用次數 */
long lLastTime; /*最近使用時間 */
long lPort; /*子進程偵聽端口號 */
EChildProcStatus EStatus; /*子進程狀態 0:空閒 1:忙碌 */
}Pool;
/*進程池狀態結構*/
typedef struct StruPoolCtrl
{
EPoolStatus EPoolStatus; /*進程池可用狀態 */
int iActProcNum; /*激活(正在使用)的進程數 */
int iInitProcNum; /*初始化進程數 */
int iValidProcNum; /*有效(總共)進程數 */
int iMaxProcNum; /*最大進程數 */
}PoolCtrl;
/***************** 全局變量 **********************/
Pool *g_SPool;
PoolCtrl *g_SPoolCtrl;
key_t SEMKEY_LOCK;
key_t SHMKEY_POOL;
key_t SHMKEY_POOLCTRL;
[/code] |
寫了個簡單的進程池,大家幫我看看有什麼問題
propool.c:
[code]
#include "propool.h"
/*************************************************
函數名稱︰AcceptWait()
函數功能︰對SemLock的封裝
輸入參數︰無
輸出參數︰無
返 回 值︰0 -- 成功
**************************************************/
int AcceptWait()
{
SemLock(SEMKEY_LOCK); /*信號燈解鎖*/
return 0;
}
/*************************************************
函數名稱︰AcceptRelease()
函數功能︰對SemLock的封裝
輸入參數︰無
輸出參數︰無
返 回 值︰0 -- 成功
**************************************************/
int AcceptRelease()
{
SemUnlock(SEMKEY_LOCK); /*信號燈解鎖*/
return 0;
}
/******************************************************************************
函數名稱: InitPool
函數功能: 進程池初始化
輸入參數: iInitNum -- 初始化進程數
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int InitPool(int iInitNum)
{
char sFileName[FILENAME_LEN];
int iRet;
int ShmID;
memset(sFileName, 0, sizeof(sFileName));
sprintf(sFileName, "%s/%s/%s", getenv("HOME"), "tmp", KEY_FILE1);
if(fclose(fopen(sFileName, "w")) == -1)
{
return -1;
}
SHMKEY_POOL = ftok(sFileName, 'a');
if(SHMKEY_POOL == -1)
{
printf("Create SHMKEY ERROR:[%s] \n", strerror(errno));
return -2;
}
SHMKEY_POOLCTRL = ftok(sFileName, 'b');
if(SHMKEY_POOLCTRL == -1)
{
printf("Create SHMKEY ERROR:[%s] \n", strerror(errno));
return -3;
}
ShmRemove(SHMKEY_POOL);
ShmRemove(SHMKEY_POOLCTRL);
/*創建共享內存*/
ShmID = ShmCreate(SHMKEY_POOLCTRL, sizeof(PoolCtrl));
if(ShmID < 0 )
{
printf("Create SHM error: [%s]\n", strerror(errno));
return -4;
}
g_SPoolCtrl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
memset(g_SPoolCtrl, 0, sizeof(g_SPoolCtrl));
/*初始化PoolCtrl結構*/
g_SPoolCtrl->;EPoolStatus = PSTATUS_ON;
g_SPoolCtrl->;iActProcNum = 0;
g_SPoolCtrl->;iInitProcNum = iInitNum;
g_SPoolCtrl->;iValidProcNum = 0;
g_SPoolCtrl->;iMaxProcNum = 0;
/*創建共享內存*/
ShmID = ShmCreate(SHMKEY_POOL, sizeof(Pool) * g_SPoolCtrl->;iInitProcNum);
if(ShmID < 0 )
{
printf("Create SHM error: [%s]\n", strerror(errno));
/*釋放已創建共享內存的資源*/
ShmUnlink((char *)g_SPoolCtrl);
ShmRemove(SHMKEY_POOLCTRL);
return -5;
}
g_SPool = (Pool *)ShmLink(SHMKEY_POOL);
memset(g_SPool, 0, sizeof(Pool) * g_SPoolCtrl->;iInitProcNum);
/*生成信號燈 的鍵值*/
memset(sFileName, 0, sizeof(sFileName));
sprintf(sFileName, "%s/%s/%s", getenv("HOME"), "tmp", KEY_FILE2);
if(fclose(fopen(sFileName, "w")) == -1)
{
/*釋放已創建共享內存的資源*/
ShmUnlink((char *)g_SPoolCtrl);
ShmUnlink((char *)g_SPool);
ShmRemove(SHMKEY_POOL);
ShmRemove(SHMKEY_POOLCTRL);
return -6;
}
SEMKEY_LOCK = ftok(sFileName, 'a');
SemRemove(SEMKEY_LOCK);
SemInit(SEMKEY_LOCK, 1);
return 0;
}
/******************************************************************************
函數名稱: IncActProcNum
函數功能: 進程池中激活子進程 增加1
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int IncActProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
SemLock(SEMKEY_LOCK); /*加鎖*/
pSPoolCtl->;iActProcNum ++;
SemUnlock(SEMKEY_LOCK); /*解鎖*/
return 0;
}
/******************************************************************************
函數名稱: DecActProcNum
函數功能: 進程池中激活子進程 減少1
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int DecActProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
SemLock(SEMKEY_LOCK);
pSPoolCtl->;iActProcNum --;
SemUnlock(SEMKEY_LOCK);
return 0;
}
/******************************************************************************
函數名稱: IncValidProcNum
函數功能: 進程池中有效子進程 增加1
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int IncValidProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
SemLock(SEMKEY_LOCK);
pSPoolCtl->;iValidProcNum ++;
SemUnlock(SEMKEY_LOCK);
return 0;
}
/******************************************************************************
函數名稱: DecValidProcNum
函數功能: 進程池中有效子進程 減少1
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int DecValidProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
SemLock(SEMKEY_LOCK);
pSPoolCtl->;iValidProcNum --;
SemUnlock(SEMKEY_LOCK);
return 0;
}
/******************************************************************************
函數名稱: GetActProcNum
函數功能: 獲取進程池中激活子進程數
輸入參數: 無
輸出參數: 無
返 回 值: 進程池中激活子進程
******************************************************************************/
int GetActProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
return pSPoolCtl->;iActProcNum;
}
/******************************************************************************
函數名稱: GetValidProcNum
函數功能: 獲取進程池中有效子進程數
輸入參數: 無
輸出參數: 無
返 回 值: 進程池中激活子進程
******************************************************************************/
int GetValidProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
return pSPoolCtl->;iValidProcNum;
}
/******************************************************************************
函數名稱: GetInitProcNum
函數功能: 獲取進程池中有效子進程數
輸入參數: 無
輸出參數: 無
返 回 值: 進程池中激活子進程
******************************************************************************/
int GetInitProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
return pSPoolCtl->;iInitProcNum;
}
/******************************************************************************
函數名稱: GetValidProcNum
函數功能: 獲取進程池中有效子進程數
輸入參數: 無
輸出參數: 無
返 回 值: 進程池中激活子進程
******************************************************************************/
int GetIdleProcNum()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
return pSPoolCtl->;iValidProcNum - g_SPoolCtrl->;iActProcNum;
}
/******************************************************************************
函數名稱: GetPoolStatus
函數功能: 獲取進程池狀態
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 不可用
1 -- 可用
******************************************************************************/
int GetPoolStatus()
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
if(pSPoolCtl->;EPoolStatus == PSTATUS_OFF)
{
return 0;
}
else
{
return 1;
}
}
/******************************************************************************
函數名稱: SetPoolStatus
函數功能: 獲取進程池狀態
輸入參數: PSTATUS_ON -- 進程池可用
PSTATUS_OFF -- 進程池不可用
輸出參數: 無
返 回 值: 0 -- 正常
******************************************************************************/
static int SetPoolStatus(EPoolStatus status)
{
PoolCtrl *pSPoolCtl;
pSPoolCtl = (PoolCtrl *)ShmLink(SHMKEY_POOLCTRL);
pSPoolCtl->;EPoolStatus = status;
return 0;
}
/******************************************************************************
函數名稱: SetPoolOn
函數功能: 設置進程池為可用狀態
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 正常
******************************************************************************/
int SetPoolOn()
{
SetPoolStatus(PSTATUS_ON);
return 0;
}
/******************************************************************************
函數名稱: SetPoolOff
函數功能: 設置進程池為不可用狀態
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 正常
******************************************************************************/
int SetPoolOff()
{
SetPoolStatus(PSTATUS_OFF);
return 0;
}
/******************************************************************************
函數名稱: GetChildProcInfo
函數功能: 根據進程號獲取子進程相關信息
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
******************************************************************************/
int GetChildProcInfo(pid_t pid, Pool *SPool)
{
int i;
Pool *pSPool;
pSPool = (Pool *)ShmLink(SHMKEY_POOL);
for(i = 0; i < GetValidProcNum(); i++)
{
if(pid == pSPool[i].iPid)
{
break;
}
}
memcpy(SPool, pSPool + i, sizeof(Pool));
return 0;
}
/******************************************************************************
函數名稱: GetChildProcInfo
函數功能: 根據索引號獲取子進程相關信息
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
******************************************************************************/
int GetChildProcInfoIndex(int index, Pool *SPool)
{
Pool *pSPool;
pSPool = (Pool *)ShmLink(SHMKEY_POOL);
memcpy(SPool, pSPool + index, sizeof(Pool));
return 0;
}
/******************************************************************************
函數名稱: CreateChildProc
函數功能: 進程池初始化
輸入參數: iInitNum -- 初始化進程數
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
static int CreateChildProc(int i, TSocket *sock)
{
Pool *pSPool;
pSPool = (Pool *)ShmLink(SHMKEY_POOL);
printf("CreateChildProc......................begin\n");
pSPool[i].iPid = getpid();
pSPool[i].lRate = 0;
pSPool[i].EStatus = CSTATUS_IDLE;
pSPool[i].lLastTime = 0;
pSPool[i].lPort = sock->;LocalPort;
/*有些進程數 +1*/
IncValidProcNum();
return 0;
}
/******************************************************************************
函數名稱: CreatePool
函數功能: 進程池初始化
輸入參數: func -- 輸入函數指針
data -- func函數輸入參數
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int CreatePool(int (*func)(int), int iForkFlag, TSocket *sock, LinkNode *link)
{
int i;
pid_t pid;
Module *pSMod;
LinkNode *pNode;
for(i = 0; i < GetInitProcNum(); i ++)
{
SetEnv_tcp(sock, atol(pSMod->;port));
switch((pid = fork()))
{
case -1:
fprintf(stderr, "FORK ERROR : [%s] \n", strerror(errno));
ClearIPC();
return -1;
case 0:
CreateChildProc(i, sock);
for(;;)
{
Accept();
}
func();
default:
continue;
}
}
return 0;
}
/******************************************************************************
函數名稱: UseChildProc
函數功能: 使用子進程
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int UseChildProc()
{
int i;
pid_t pid;
Pool *pSPool;
pSPool = (Pool *)ShmLink(SHMKEY_POOL);
pid = getpid();
for(i = 0; i < GetValidProcNum(); i ++)
{
if(pSPool[i].iPid == pid)
{
break;
}
}
/*置進程狀態為忙碌*/
pSPool[i].EStatus = CSTATUS_ACT;
pSPool[i].lLastTime = atol(GetSysTime());
/*此進程被使用次數 +1*/
pSPool[i].lRate ++;
IncActProcNum();
return 0;
}
/******************************************************************************
函數名稱: RlsChildProc
函數功能: 釋放子進程
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int RlsChildProc()
{
int i;
pid_t pid;
Pool *pSPool;
pSPool = (Pool *)ShmLink(SHMKEY_POOL);
pid = getpid();
for(i = 0; i < GetValidProcNum(); i ++)
{
if(pSPool[i].iPid == pid)
{
break;
}
}
/*激活進程數減 1*/
DecActProcNum();
/*置進程狀態為空閒*/
pSPool[i].EStatus = CSTATUS_IDLE;
return 0;
}
/******************************************************************************
函數名稱: MonitorPool
函數功能: 監控進程池
輸入參數: 無
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int MonitorPool()
{
int i;
Pool *pSPool;
pSPool = (Pool *)ShmLink(SHMKEY_POOL);
while(1)
{
for(i = 0; i < GetValidProcNum(); i ++)
{
/*
* 如果為異常進程,則重置此子進程
*/
if( pSPool[i].iPid >; 0 && kill(pSPool[i].iPid, 0) != 0)
{
pSPool[i].iPid = 0;
pSPool[i].EStatus = CSTATUS_IDLE;
pSPool[i].lRate = 0;
pSPool[i].lLastTime = 0;
}
}
}
}
/******************************************************************************
函數名稱: ClearPool
函數功能: 釋放進程池
輸入參數: iFlag -- 是否強制關閉進程池(即 當子進程正在處理交易時,是否強制關閉它)
1: 當子進程空閒時 才能被殺掉
輸出參數: 無
返 回 值: 0 -- 成功
<0 -- 失敗
******************************************************************************/
int ClearPool(int iFlag)
{
int i;
time_t t0;
for(i = 0; i < GetValidProcNum(); i ++)
{
if(iFlag == 1)
{
t0 = time(NULL);
while(g_SPool[i].EStatus == CSTATUS_ACT)
{
/*超時時間*/
if(time(NULL) - t0 >; OFF_WAITTIME)
{
break;
}
}
}
if(g_SPool[i].iPid >; 0)
{
kill(g_SPool[i].iPid, SIGTERM);
}
}
ClearIPC();
free(g_SPool);
free(g_SPoolCtrl);
return 0;
}
[/code] |
寫了個簡單的進程池,大家幫我看看有什麼問題
main.c:
[code]
創建socket鏈接
InitPool(5);
CreatePool(func, sockset,......);
MonitorPool();
[/code] |
寫了個簡單的進程池,大家幫我看看有什麼問題
這裡面用到了不少的其它的庫,Shm..., Sem...., Tcp...。
CreateChildProc中,怎麼一個服務的機制沒看的太懂。
只能提點表面的意見了:
全局量一般在c源文件中定義,而不是在頭文件,頭文件最多只放聲明。一般來說,也盡量是封裝全局量
你的monitorpool過程似乎在不停的檢查,沒有個等待?而且你最好也需要先判斷這個pid是不是屬於你的子進程,而不是直接kill. |
寫了個簡單的進程池,大家幫我看看有什麼問題
服務是在 CreatePool 函數里 , Accept()偵聽, func()處理
monitorpool 只是針對 pSPool 中的 進程號 不斷掃瞄, 即只針對 進程池中的 子進程 掃瞄 |
寫了個簡單的進程池,大家幫我看看有什麼問題
子進程負責accept,這個個能在一些系統中需要加入其它的措施。
管理子進程寫了不少,但是如果子進程core dump了(異常退出),怎麼處理?至少應該有restart子進程和初始化該進程資源的功能。 |
寫了個簡單的進程池,大家幫我看看有什麼問題
monitorpool 只是針對 pSPool 中的 進程號 不斷掃瞄, 即只針對 進程池中的 子進程 掃瞄
這種掃面是浪費CPU,用以個簡單的進程建通信的機制便可,例如pipe都可以,這樣讓發生變化的子進程來喚醒父進程,這樣實現管理可能效率能高一些。 |
寫了個簡單的進程池,大家幫我看看有什麼問題
monitorPool現在寫的比較簡單,
對於子進程異常中止, 或 coredump , 應重新fork 一個子進程 |
| |