- 论坛徽章:
- 0
|
在我的第一个linux下多线程代码中,有一个主线程5个同样级别的子线程,当这个程序收到外部的SIGINT信号时,我想让主线程捕捉到该信号,并且向5个子线程发送消息告知它们保存现有工作并结束退出,此时主线程进入等待子线程结束状态.这5个子线程收到该消息后暂停现有工作并保存退出,当最后一个线程退出前,告诉主线程所有子线程均已退出.主线程被唤醒,处理结束工作并且退出.现有几点疑问:
1.主线程如何向5个子线程发送消息,如果是用pthread_kill()函数,那子线程不是要一直轮询等待该消息的到来?如果是用signal()给线程安装信号处理函数,我试过好像是所有的线程共享一个signal handler,这样的话当消息到来,不是所有的线程都会被中断(所谓的"惊群"现象?)?
2.是不是所有的signal handler都是"不可重入"的?我的意思是当线程/进程执行signal handler函数时,如果又来一个信号,会被再次中断而去执行另外一个signal handler吗?
3.整个程序中,是否只要一个mutex就可以了?假如我的代码中有两处需要互斥,这两处的代码涉及到不同的变量,需要两个互斥量保护还是一个?
4.我需要自己定义一个signal,比如叫SIGMY,怎么定义怎么操作呢?
初次尝试linux多线程编程,望多指点.
以下是我的代码:
struct dsConf
{
int nMaxThread;
int iSyncPort;
int iSendPort;
char sDBHost[20];
char sDBName[20];
char sDBUser[10];
char sDBPwd[15];
};
typedef tid pthread_t;
typedef SOCKET int;
struct spth
{
tid id;
SOCKET soClient;
int status; // -1:exited 0:idle 1:processing 2:done and wait recyle
};
#define PSIGOVER 200
#define PSIGCANCEL 201
void* ThreadMain(void *arg);
tid MakeThread(struct spth *arg);
void GetConfig();
/**********signal handler*********/
void sigINT(int sig);
void sigOVER(int sig);
void sigCANCEL(int sig);
/*************global vars***************/
struct dsConf dsc; //config structure
tid iMainThread; //main thread id
pthread_mutex_t mutexCli;
pthread_cond_t condCli;
pthread_mutex_t mutexINT;
pthread_cond_t condINT;
struct spth *ppth; //structure stores threads info
int iPthExit;
int main(int argc,char** argv)
{
int i;
int nClient; //current clients being handled
SOCKET solisten; //listen socket
SOCKET socli; //incoming client socket
socklen_t soclilen;
struct sockaddr_in cliaddr, svraddr;
/********Make usage format*********/
/********Init the varibals*********/
ppth = (struct spth*)calloc(ddc.nMaxThread,sizeof(struct spth));
bzero(ppth,ddc.nMaxThread*sizeof(struct spth));
nClient = 0;
iPthExit = 0;
iMainThread = pthread_self();;
pthread_mutex_init (&mutexCli, NULL);
pthread_cond_init (&condCli, NULL);
pthread_mutex_init (&mutexINT, NULL);
pthread_cond_init (&condINT, NULL);
GetConfig();
/********Create threads to handle clients*********/
for(i=0;i<dsc.nMaxThread;i++)
ppth.id = MakeThread( &(ppth) ); //pre-create thread spool and record the thread id into ppth
/********Install signal handler*********/
Signal(SIGINT, sigINT);
Signal(PSIGOVER, sigOVER);
/********Listen and accept clients*********/
solisten = Socket (AF_INET, SOCK_STREAM, 0);
bzero(&svraddr, sizeof(svraddr));
svraddr.sin_family = AF_INET;
svraddr.sin_addr.s_addr = htonl (INADDR_ANY);
svraddr.sin_port = htons (dsc.iSyncPort);
Bind(solisten, (struct sockaddr*)&svraddr, sizeof(svraddr));
Listen(solisten, BACKLOG);
while(1)
{
//get a incoming client
soclilen = sizeof(cliaddr);
socli = Accept(solisten, (struct sockaddr*)&cliaddr, &soclilen);
//select an idle thread to handle it
if(nClient == dsc.nMaxThread)
//too many clients right now!
else
{
for(i=0;i<dsc.nMaxThread;i++)
{
if(ppth.status == 1)
break; //so ppth is the selected thread
}
}
pthread_mutex_lock(&mutexCli);
ppth.soClient = socli;
ppth.status = 1;
nClient++;
pthread_cond_broadcast(&condCli);
pthread_mutex_unlock(&mutexCli);
}
}
void* ThreadMain(void *arg)
{
struct spth *pth;
SOCKET soConn;
pth = (struct spth*)arg;
pthread_detach(pthread_self());
Signal(PSIGCANCEL,sigCANCEL);
while(1)
{
pthread_mutex_lock (&mutexCli);
while(pth->;status == 0)
pthread_cond_wait(&condCli, &mutexCli);
pthread_mutex_unlock(&mutexCli);
soConn = pth->;soClient;
//do with socket soConn
//...
pthread_mutex_lock (&mutexCli);
pth->;status = 2;
pthread_mutex_unlock(&mutexCli);
pthread_kill(iMainThread,PSIGOVER);
}
return NULL;
}
tid MakeThread(struct spth *arg)
{
tid iNewtid;
Pthread_create(&iNewtid, NULL, &ThreadMain,(void*)arg);
return iNewTid;
}
void sigINT(int sig)
{
int i;
for(i=0;i<dsc.nMaxThread;i++)
pthread_kill(ppth.id, PSIGCANCEL);
pthread_mutex_lock (&mutexINT);
while(nClient >; 0)
pthread_cond_wait(&condINT, &mutexINT);
pthread_mutex_unlock(&mutexINT);
exit(0);
}
void sigOVER(int sig)
{
int i;
pthread_mutex_lock(&mutexCli);
for(i=0;i<dsc.nMaxThread;i++)
{
if(ppth.status == 2) //cleanup the thread
{
Close(ppth.soClient,CLOSE_ALL);
ppth.soClient = 0;
ppth.status = 0;
}
}
nClient--;
pthread_mutex_unlock(&mutexCli);
return;
}
void sigCANCEL(int sig)
{
int i;
//each thread finish or save its current job and exit
//...
pthread_mutex_lock(&mutexINT);
for(i=0;i<dsc.nMaxThread;i++)
{
if(ppth.id == pthread_self())
if(ppth.status >; 0)
{
Close(ppth.soClient,CLOSE_ALL);
ppth.status = -1;
nClient--;
}
}
if(nClient == 0)
pthread_cond_signal(&condINT);
pthread_mutex_unlock(&mutexINT);
pthread_exit(NULL);
} |
|