带有 wait(NULL) 的 C 程序没有像它应该的那样结束

C programm with wait(NULL) doesnt end like it should

我写了这段代码,它应该有 N 个生产者 (P) 和一个消费者 (C)。这两个交换 K 消息,它们位于两个单独的共享内存段 (sms) 中。 P 向 C 发送一行和他们的 pid。 C 发回此行,并用发送它的 P 的 pid 大写。当发送了 K 条消息后,C 必须计算并打印出 P 读取了自己的大写消息的次数。我在最后放了一个 wait(NULL) 以便 C 等待所有 P 将他们的个人 pid_match 放入第三条短信的缓冲区中,以便它可以在之后读取正确的值。相反,当我执行代码时,它只从第一个 P 读取 pid_match 然后终止。为什么会这样。我post下面的代码。如果有什么执行的例子有用我可以提供。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>   
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/sem.h>
    #include <string.h>
    #include <ctype.h>
    #include <time.h>
    #include "myheader.h"

    int main (int argc , char* argv[]){

    if(argc<3) {
      printf("Programm needs more arguments (K and N) \n");
    return(-1);
}
else
{
    const int SHMSIZE = sizeof(struct message);             // Shared Memory size = the size of a message
    int K, N, k, n, child_pid, shmid_in, shmid_out, shmid_pid, full_in, empty_in, full_out, empty_out, empty_pid, full_pid, pid_match=0,status,G;
    key_t shmkey_in, shmkey_out, semkey0_in, semkey1_in, semkey0_out, semkey1_out;
    struct message *shm_in, *shm_out;
    int *shm_pid;
    //struct sembuf oparray[1]={0,1,0};


    K=atoi(argv[1]);
    N=atoi(argv[2]);
    const int shm_pidsize = N*sizeof(int);

    if(K==0 || N==0) return 0; //if no producers exist the programm should exit
    printf("%d %d \n", K, N );


    /* --- Keys Initialization --- */
    shmkey_in = ftok("/OS1.c", 1);
    shmkey_out = ftok("/OS1.c", 2);

    semkey0_in = ftok("/OS1.c", 3);     // full_in semkey
    semkey1_in = ftok("/OS1.c", 4);     // empty_in semkey          Tou P oi 2 gia to sms in (apo P se C dld)

    semkey0_out = ftok("/OS1.c", 5);        // full_out semkey      
    semkey1_out = ftok("OS1.c", 6);     // empty_out semkey         Tou P oi 2 gia to sms out (apo C se P dld)


    /* --- Shared memory creation --- */
    shmid_in = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
    shmid_out = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
    shmid_pid = shmget(IPC_PRIVATE,shm_pidsize,IPC_CREAT | 0666);       // shm_pid creation

    shm_in = (struct message*)shmat(shmid_in,NULL,0);
    shm_out = (struct message*)shmat(shmid_out,NULL,0);
    shm_pid = (int*)shmat(shmid_pid,NULL,0);        // shm_pid attach


    /* --- Semaphore creation --- */
    full_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
    empty_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);

    full_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
    empty_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);

    full_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
    empty_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);


    /* --- Semaphore Initialization --- */
    union semum init0,init1;

    init0.val=0;
    init1.val=1;

    semctl(full_in,0,SETVAL,init0);     // full_in = 0
    semctl(empty_in,0,SETVAL,init1);    // empty_in = 1


    semctl(full_out,0,SETVAL,init0);    // full_out = 0
    semctl(empty_out,0,SETVAL,init1);   // emty_out = 1


    semctl(full_pid,0,SETVAL,init0);        // pid_full = 0
    semctl(empty_pid,0,SETVAL,init1);       // pid_empty = 1


    /* --- Semaphore oparations buffers --- */
    struct sembuf full_in_up = {0,1,0};
    struct sembuf full_in_down = {0,-1,0};
    struct sembuf empty_in_up = {0,1,0};                // Operations of P to semaphores 0,1,2
    struct sembuf empty_in_down = {0,-1,0};

    struct sembuf full_out_up = {0,1,0};
    struct sembuf full_out_down = {0,-1,0};
    struct sembuf empty_out_up = {0,1,0};               // Operations of C to semaphores 0,1,2
    struct sembuf empty_out_down = {0,-1,0};

    struct sembuf full_pid_up = {0,1,0};
    struct sembuf full_pid_down = {0,-1,0};
    struct sembuf empty_pid_up = {0,1,0};
    struct sembuf empty_pid_down = {0,-1,0};

    for(n=0; n<N; n++)
    {


        child_pid = fork();
        //printf("child_pid = fork();\n ");
        if (child_pid == 0)
        {
            printf(" --- this is %d th child with pid: %d---\n \n", n, getpid());
            int pid_match = 0;      // Initialize pid_match
            while(1){
                        //printf("int pid_match = 0;        // Initialize pid_match\n while(1){\n");
                        // printf("%d \n",semctl(empty_in,0,GETVAL));
                        // sleep(1);
                        semop(empty_in, &empty_in_down,1); // down(empty_in)
                        // printf("%d \n",semctl(empty_in,0,GETVAL));
                        //printf(" down(empty_in)\n");                      
                        struct message msg;
                        msg.pid = getpid();

                        char buf[max_line_length];
                        FILE *ptr_file;     
                        ptr_file =fopen("input.txt","r");
                        if (!ptr_file) perror("File failed to open");
                        long curtime = time(NULL);
                        srand((unsigned int) curtime);      
                        sleep(1);                       // produce & send
                        int i=1, j=0, luckyline = rand() % 5 + 1;
                        //printf("%d\n", luckyline);
                        while (fgets(buf, 1000, ptr_file)!=NULL && i<5)
                        {

                            if (i == luckyline)
                            {
                                //printf("%s \n",buf);
                                strcpy(msg.line,buf);   // complete the message

                                strcpy(shm_in->line,msg.line);  // send message to sms
                                shm_in->pid = getpid();
                                //printf("pid = %d\n",shm_in->pid );
                                break;
                            }
                            i++;
                        }



                        fclose(ptr_file);

                        // strcpy(shm_in->line, "message");
                        // printf("message copy\n");
                        // shm_in->pid = child_pid;


                        semop(full_in,&full_in_up,1);  // up full
                        //printf("shared memory in full \n");

                         // read from C and kill if K messages have been sent
                        semop(full_out,&full_out_down,1);   // down full

                        //if (strcmp(shm_out->line,"kill")!=0) printf("%s\n", shm_out->line);


                        if (strcmp(shm_out->line,"kill") == 0)      
                        {
                            semop(empty_pid,&empty_pid_down,1);

                            shm_pid[j]=pid_match;
                            j++;

                            semop(full_pid,&full_pid_up,1);
                            printf("%d pid_match = %d\n",getpid(),pid_match );
                            printf("kill\n");
                            exit(1);
                        }

                        if (shm_out->pid == getpid())
                        {
                            //strcpy(shm_out->line,"[=10=]");                                               shm_out->pid = 0;
                            printf("Pid's match\n");
                            pid_match++;                    
                        }


                        semop(empty_out,&empty_out_up,1);   // empty up

                    }
                    //sleep(20);

        }else if(child_pid < 0){
            perror("fork failed\n");
        }else
        {
            // break;
        }
    }

    for (k=0; k<K; k++)
    {
        int j=0;
        struct message m_out;
        //printf("Consumer running\n");
        semop(full_in,&full_in_down,1); //down full _in
        //sleep(1);
        //printf("Full got 'downed'\n");
        m_out.pid = shm_in->pid;
        while (shm_in->line[j] != '[=10=]')
            {
                m_out.line[j] = toupper(shm_in->line[j]);           // write in m_out->line the content of shm_in->line capitalized
                j++;
            }
        /*if (k == K)
        {
            printf("kill\n");
            strcpy(shm_out->line, "kill");

        }*/

        semop(empty_in,&empty_in_up,1); //up empty_in



        semop(empty_out,&empty_out_down,1); // down empty_out

        //printf("shm_in->line = %s \n", shm_in->line );
        // m_out->line = shm_in->line;                              // capitalize & send
        //strcpy(shm_out->line,m_out.line);
        //shm_out->pid = m_out.pid;                 

        printf("shm_in->line = %s \n", shm_in->line );
        strcpy(shm_out->line,m_out.line);
        printf("shm_out->line = %s\n", shm_out->line);
        shm_out->pid = m_out.pid;


        semop(full_out,&full_out_up,1); //up full
    }

        if (k == K)
        {
            printf("C kill\n");
            semop(empty_out,&empty_out_down,1);
            strcpy(shm_out->line, "kill");
            semop(full_out,&full_out_up,1);

        }

    wait(NULL);
    //sleep(2);
    //printf("pid_match = %s\n",pid_match);
    for(G=0; G<N; G++){
        //sleep(2);
        pid_match += shm_pid[G];
        //printf("(pid_match = %s\n",pid_match);
        if(G == N-1)
        printf("Completed execution, exit %d\n",pid_match );
    }

    /* --- TERM ---*/
semctl(full_out,0,IPC_RMID,0);
semctl(full_in,0,IPC_RMID,0);
semctl(empty_out,IPC_RMID,0);
semctl(empty_in,0,IPC_RMID,0);
semctl(full_pid,0,IPC_RMID,0);
semctl(empty_pid,0,IPC_RMID,0);

shmdt(shm_pid);
shmdt(shm_in);
shmdt(shm_out);
}


return 0;

}

NULL参数的wait函数只等待一个个子进程退出。然后它停止等待。

您需要等待所有进程退出。

您可以通过保存所有子进程 pid 来做到这一点,然后循环等待直到它们全部退出(使用 wait 的 return 值进行检查)。