Setelah garpu (), di mana anak mulai dieksekusi?

22

Saya mencoba mempelajari pemrograman UNIX dan menemukan pertanyaan mengenai fork (). Saya mengerti bahwa fork () menciptakan proses identik dari proses yang sedang berjalan, tetapi di mana ia mulai? Misalnya, jika saya punya kode

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

Outputnya adalah:

Ini jelas merupakan proses induk. Proses
mana yang mencetak ini?
Proses mana yang mencetak ini?

Saya pikir itu fork()menciptakan proses yang sama, jadi saya awalnya bahwa dalam program itu, fork()panggilan akan secara rekursif dipanggil selamanya. Saya kira proses baru dibuat dari fork()awal setelah fork()panggilan?

Jika saya menambahkan kode berikut, untuk membedakan antara proses induk dan anak,

if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());

setelah panggilan fork (), di mana proses anak memulai eksekusi?

Gilles 'SANGAT berhenti menjadi jahat'
sumber
5
man forkcukup yakin untuk menjawab pertanyaan Anda, btw
alex

Jawaban:

23

Proses baru akan dibuat dalam fork()panggilan, dan akan mulai dengan kembali darinya seperti induknya. Nilai pengembalian (tempat Anda menyimpan retval) berasal dari fork():

  • 0 dalam proses anak
  • PID anak dalam proses induk
  • -1 pada orang tua jika ada kegagalan (tidak ada anak, tentu saja)

Kode pengujian Anda berfungsi dengan benar; ia menyimpan nilai balik dari fork()dalam child_piddan digunakan ifuntuk memeriksa apakah 0 atau tidak (meskipun tidak memeriksa kesalahan)

Michael Mrozek
sumber
13

Saya berpikir bahwa fork () menciptakan proses yang sama, jadi saya awalnya bahwa dalam program itu, fork () akan dipanggil secara berulang selamanya. Saya kira proses baru yang dibuat dari fork () dimulai setelah panggilan fork ()?

Iya nih. Mari beri nomor garis:

int main (int argc, char **argv)
{
    int retval;                                               /* 1 */
    printf ("This is most definitely the parent process\n");  /* 2 */
    fflush (stdout);                                          /* 3 */
    retval = fork ();                                         /* 4 */
    printf ("Which process printed this?\n");                 /* 5 */
    return (EXIT_SUCCESS);                                    /* 6 */
}

Alur eksekusi adalah:

caller process     fork()  ...
                          
original program            exec()  2  3  4  5  6
                                               
forked program                                   5  6

... yang menjelaskan dengan tepat keluaran yang Anda terima.

Jika Anda ingin tahu bagaimana program asli dan bercabang mungkin dapat berperilaku berbeda, karena mereka harus berbagi kode yang sama, lihat jawaban Michael Mrozek.

badp
sumber
Perhatikan bahwa 1 sebenarnya bukan instruksi. Perhatikan juga bahwa program asli dan bercabang tidak benar-benar berjalan pada saat yang sama - salah satu harus menunggu yang lain untuk menghasilkan / didahului.
badp
1
Pada sistem multi-core / multi-cpu, kedua program sebenarnya dapat berjalan pada saat yang sama.
jlliagre
@jilliagre Sistem multicore benar-benar tentang multithreading. Adapun sistem dengan banyak CPU, saya tidak tahu apakah itu yang terjadi atau tidak dalam praktek. Saya bukan ahli dalam bidang ini - dan sepertinya skenario yang tidak mungkin. Jika kami setuju bahwa OS dapat menjalankan banyak proses pada saat yang sama (lalu bagaimana cara menangani konkurensi?), Pada saat program asli menjalankan instruksi 4 pada CPU, CPU lain kemungkinan sibuk menjalankan proses lain pula.
badp
Saya akan mengatakan itu adalah skenario yang sangat mungkin, terutama karena ada panggilan sistem yang mendasarinya dengan beberapa I / O terjadi pada langkah 5. Memiliki semua CPU sibuk sebenarnya bukan situasi yang umum karena CPU jarang menjadi hambatan dengan mesin saat ini. Sepertinya Anda juga membingungkan multi-threading dan multi-core.
jlliagre
8
Bisakah saya berkomentar mengatakan panah diagonal itu fantastis .
JBirch
0

Solusi nyata untuk ini adalah

switch (fork()) {
    case -1 :
        fprintf (stderr, "fork failed (%s)\n", strerror(errno));
        break;
    case 0 :  // child process comes here
        break;
    default : // parent process
        break;
}

// all continue here
ott--
sumber
-1

apa pun kode setelah fork(), disalin ke proses anak, dan jangan campur proses induk dan anak, mereka adalah dua entitas yang berbeda, yang memiliki lingkungan yang sama (digandakan, tidak dibagi).

Sekarang lihat output Anda ...

pengguna2670535
sumber