【问题标题】:Avoid zombies when father is in a wait of a semaphore当父亲在等待信号时避免僵尸
【发布时间】:2013-04-23 17:23:38
【问题描述】:

这是一个奇怪的问题。我有 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,然后等到child结束,再fork。 我需要父亲 fork 这么多时间,并且不要等到进程结束再分叉。

但是没有waitpid,问题是另一个问题。因为在那之后他开始接收所有消息所需的所有进程,父亲控制并仍然等待来自客户端的另一个信号(第一个等待(sem,1 ) ),留下这么多僵尸进程。

我不知道我解释得好不好。。英语很难-_-

所以,我想要一个服务器,它接收到信号,分叉很多次。任何孩子接受信息并做一些事情,然后孩子结束。同时服务器继续等待新的传入消息。一切都没有制造僵尸:)

【问题讨论】:

  • 您想要为收到的每条消息创建一个新进程,或者,您希望多个进程同时接收多条消息?
  • 我希望为收到的每条消息创建一个新进程!
  • 哦,我必须说,我可以多次运行客户端,全部运行,然后一条消息,然后启动 3 个客户端,每个发送 10 条消息
  • 尝试更改 fork 和 msgrcv 之间的顺序。先接收msg,然后fork处理,不使用waitpid。
  • 不要改变..问题仍然是任何对客户端的调用,使服务器进程僵尸..因为主服务器在子进程结束之前取得控制权,它仍然在等待对于信号量..

标签: c signals semaphore wait zombie-process


【解决方案1】:

一种无需担心僵尸进程的即发即弃进程的方法是分叉两次。

每个进程都有一个父进程。如果父进程在子进程之前退出,则子进程将成为孤儿,并由init(进程 1)继承 - 这将等待所有子进程,防止他们在没有手动操作的情况下成为僵尸。

所以你可以做的是在子进程中分叉,然后再分叉。然后,您可以让孩子退出,这将导致孙子(您工作的地方)被init 继承。父进程可以为子进程wait(这不会花费很长时间,因为子进程除了分叉并退出之外什么也没做)。当孙子退出时,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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多