这是一个奇怪的问题。我有2个不同的程序: 服务器和客户端。
服务器启动,分配所有消息队列并开始等待来自客户端的信号(该信号用于告知服务器“有新消息”)。 服务器保持无限循环,直到重新发送SIGQUIT。 客户端在投入时,开始向服务器发送大量消息
for(;;){//infinite loop
wait(sem,1); //wait for new message
rc = msgctl(msgid, IPC_STAT, &qbuff);
seq_num++;
pid=fork(); //new process for take the message
if(!pid){
if((msgrcv(msgid, &q, msgsz, 1,MSG_NOERROR))== -1)
perror("msgrcv error");
else{
pthread_mutex_lock(&mutex); //start critic sector
printf("\nthere is a prenotation\n");
q.price=get_conf_value(q.kindof_service)+(q.priority*get_conf_value(3)); //costo = costo_visita + (priorità * costo_priorità)
q.turn=seq_num-q.priority; //assign turn
pthread_mutex_unlock(&mutex); //end critic sector
if(q.turn<0)q.turn=0; //controllo del turno che non sia minore di 0
printf("---------------------------");
printf("\nPrenotation number %i\npid caller: %i\npriorità: %i\n for %i\ncost %i\nturn %i\n",seq_num,q.clientId,q.priority, q.kindof_service ,q.price, q.turn);
printf("---------------------------\nPrenotation ok\n\n\n");
}
printf("\nsuccess.\n");
exit(1); //close children process
}
}
问题在于,父亲以这种方式离开了这么多僵尸。如果我添加
else{//i am the father
waitpid(pid, 0, 0);
}
存在主进程fork的问题,然后等到子进程结束,然后再次fork。 我需要父亲分叉这么多时间,不要再等待分叉前的过程结束。
但是没有waitpid问题是另一个......因为在那之后他开始接收所有消息所需的所有过程,父亲接受控制并仍然等待来自客户端的另一个信号(第一次等待(sem,1) )),留下如此多的僵尸进程。
我不知道我是否解释得很好......在英语中非常困难-_-
所以,我想要一台收到信号的服务器多次拨号。任何孩子都会留言并做一些事情,然后孩子就会结束。同时服务器继续等待新的传入消息。所有没有制作僵尸的人:)
答案 0 :(得分:1)
在不必担心僵尸的情况下发射并忘记进程的一种方法是分叉两次。
每个流程都有一个父流程。如果父进程在子进程之前退出,则该进程将成为孤儿,并由init
继承(进程1) - 这将等待所有子进程,防止他们在没有手动工作的情况下成为僵尸。
所以你可以做的是在子进程中再次fork和fork。然后,您可以让孩子退出,这将导致孙子(您在哪里工作)被init
继承。父进程可以wait
为子进程(这不会花很长时间,因为孩子除了fork和exit之外什么都不做)。当孙子退出时,init
会自动wait
。
/* fire and forget */
int execute_detached(char **cmdline)
{
pid_t pid;
if((pid = fork()) < 0) { /* fork error */
perror("fork");
return 0;
}
else if(pid > 0) { /* parent */
waitpid(pid, NULL, 0);
return 1;
}
else { /* child */
if((pid = fork()) < 0) { /* fork error */
perror("fork");
return 0;
}
else if(pid > 0) { /* child */
/* make grand child an orphan */
_exit(0);
}
else { /* grand child */
execvp(cmdline[0], cmdline);
perror("execvp");
_exit(1);
}
}
return 0;
}