Mencoba membuat 2 proses anak dan 1 cucu yang berjalan secara berurutan

Jadi saya mencoba membuat 2 proses anak dan satu proses cucu dari anak pertama. Saya mencoba menjalankan proses anak pertama, lalu cucu, lalu anak kedua dengan orang tua memanggil pid ketika proses selesai. Saya benar-benar buntu - Saya memiliki banyak versi kode dari kode tersebut tetapi tidak dapat mengaktifkannya dalam urutan yang benar. Bantuan, saran, atau tautan apa pun akan sangat dihargai.

Output yang diinginkan adalah

-Saya anak pertama

----Akulah cucunya

Saya orang tuanya, anak pertama memiliki pid 21505

-Saya anak pertama, cucu punya pid 21506

-Coba lagi

--Saya anak kedua

-- -->Anak kedua: 1317 byte ditransfer.

Saya orang tuanya lagi, anak kedua punya pid 21507

Induk - Anak 21507 selesai

-Coba lagi

**** akan melihat 20 baris pertama file lab4.c di sini

Induk - Anak lainnya 21505 selesai

int main(int* argc, char* args[])
{
pid_t child1, child2, gchild; //process ids
child1 = fork();           //Create the two child processes
if (child1 == 0)
{ // parent
    child2 = fork();
    if (child2 == 0)
    { //parent
        printf("P: first child has pid %d\n", child1);
        printf("P: second child has pid %d\n", child2);

        pid_t wpid; // process id that is finished
        int status; //status code returned by process  
                    //Wait for all child processes to complete
        while ((wpid = wait(&status)) > 0)
        {
            if (wpid > 0)
            {
                printf("P: Child %d is done \n", wpid);
            }
        };

        exit(0); //exit main parent process
    }
    else
    {
        //Second process's code

        printf("SC: I am the second child.\n");
        int totalBytes = 0; //total number of bytes in the file we are going to read in
        char buffer[2056]; //file contents size 2056 bytes
        ssize_t read_bytes = 0; //Bytes from each chunk get placed here temporarily

        ///Read in file contents: home/common/lab_sourcefile
        int fd_in = open("/home/COIS/3380/lab4_sourcefile", O_RDONLY);//open the file
        do
        {
            //read the file chunk by chunk to the buffer
            read_bytes = read(fd_in, buffer, (size_t)2056);

            // End of file or error.
            if (read_bytes <= 0)
            {
                break; //done reading file
            }

            //Save the total number of bytes
            totalBytes = totalBytes + read_bytes;
        } while (1); //infinite loop until we are done reading the file

        //Write out contents to: lab4_file_copy
        char filepath[1024]; //temp path
        getcwd(filepath, sizeof(filepath)); //Get the current working directory
        strcat(filepath, "/lab4_file_copy"); //Tack on the filename
        int fd = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); //open the file. O_RDWR = read and write flag, O_CREAT = create if doesnt exist, S_* flags are permission flags from fstat 
        write(fd, buffer, strlen(buffer)); //write to the file

        close(fd_in);//close file we were reading
        close(fd); //close copy file

        // print out the number of bytes the file
        printf("SC: --> Second child: %d bytes transferred.\n", totalBytes);

        exit(0); //done kill second child process
    }
}
else
{
    //First child process

    printf("FC: I'm the first child.\n");

    //Create the granchild process
    gchild = fork();
    if (gchild == 0)
    {
        printf("GC: I am the grandchild.\n");

        sleep(3); //sleep for 3 seconds

        printf("GC: #### Output start ####\n");
        execlp("head", "head", "-n", "20", "l.c", NULL); //this should exit automatically
        printf("ERROR: execlp command failed\n");//This will only run if the execlp process fails
        exit(1); //FAILED!
    }
    else
    {
        //Output the granchild pid
        printf("FC: I am the first child, grandchild has pid %d\n", gchild);
        int grandchildStatus;
        //Wait for grandchild process to be done. Polling...
        while ((waitpid(gchild, &grandchildStatus, WNOHANG)) != gchild)
        {
            printf("FC: Try again\n");
            sleep(1);
        };
        printf("GC: #### Output end ####\n");
        //End of first child. Grandchild must have completed.

        exit(0); //Done. kill first child process
    }
}

}


person sidelaunch    schedule 09.11.2017    source sumber
comment
Jika Anda menukar saluran ke-3 dan ke-4, Anda cukup melakukan sinkronisasi dengan wait panggilan setelah setiap percabangan. Jika Anda menginginkannya apa adanya, Anda memerlukan mekanisme sinkronisasi tambahan. Ada banyak pilihan: pipa, sinyal, semafor memori bersama, dll. Silakan pilih.   -  person PSkocik    schedule 09.11.2017
comment
belajar semaphore.   -  person Christian Gibbons    schedule 09.11.2017


Jawaban (1)


Pada dasarnya ada dua bug dalam program Anda:

  • Bagian else terakhir:

    Anda memanggil fork sehingga semua yang muncul setelah fungsi fork akan dieksekusi di kedua proses.

    Baik orang tua dan anak kedua akan mencetak: "Saya orang tua, anak pertama memiliki pid..."

    Untuk memperbaikinya, Anda harus menambahkan if(child2 == 0) (dalam blok else)...

  • Urutan instruksi:

    Saat Anda memulai proses anak, proses anak akan benar-benar berjalan pada waktu yang sama dengan proses induk:

    Jika salah satu proses mencetak "Halo dunia." dan proses lainnya mencetak "Ini adalah ujian." Anda mungkin melihat teks berikut di layar: "Ini Halo adalah dunia. ujian." (atau serupa) karena kedua proses tersebut adalah menulis ke layar secara bersamaan.

    Anda dapat menggunakan fungsi waitpid di induk proses anak untuk menunggu hingga proses anak selesai untuk memastikan bahwa anak telah selesai sebelum induk melanjutkan (mencetak teks).

    Namun jika Anda ingin mencetak teks dalam proses induk terlebih dahulu, Anda harus menemukan cara untuk menghentikan proses anak dan menunggu proses induk selesai mencetak.

    Misalnya, Anda mungkin menggunakan raise(SIGSTOP); untuk menghentikan proses yang sedang berjalan. Pada proses lain gunakan kill(pid, SIGCONT); untuk melanjutkan proses lain pid yang menunggu:

    child = fork();
    if(child == 0)
    {
        raise(SIGSTOP); /* Wait for the parent */
        /* Do something */
    }
    else
    {
        /* Do something */
        kill(child, SIGCONT); /* Tell the child to continue */
    }
    

... namun: Seperti yang disebutkan PSkocik, bahkan dalam kasus ini, program Anda mungkin hang - jadi tidak semudah itu!

person Martin Rosenau    schedule 09.11.2017
comment
Bagaimana jika SIGCONT dikirim sebelum SIGSTOP? - person PSkocik; 09.11.2017