Çataldan sonra () çocuk idamına nerede başlar?


22

UNIX programlamasını öğrenmeye çalışıyorum ve fork () ile ilgili bir soru ile karşılaştım. Ben fork () şu anda çalışan sürecin özdeş bir işlem oluşturduğunu anlıyorum, ama nerede başlıyor? Örneğin, kodum varsa

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);
}

Çıktı:

Bu kesinlikle ana süreçtir
Bu süreç hangi süreci basar?
Bunu hangi süreç bastırdı?

fork()Aynı işlemi yarattığını düşündüm , bu yüzden başlangıçta bu programda fork()çağrının tekrarlı olarak çağrılacağını düşündüm . Sanırım aramadan fork()sonra başlayan yeni süreç fork()?

Bir üst ve alt işlem arasında ayrım yapmak için aşağıdaki kodu eklersem,

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 ());

fork () çağrısından sonra, çocuk süreci yürütmeye nerede başlar?


5
man forksorunuzu cevaplamak için yeterince emin, btw
alex

Yanıtlar:


23

Yeni işlem fork()çağrı içinde oluşturulacak ve aynı ebeveyn gibi geri dönerek başlayacaktır. (İçinde sakladığınız retval) dönüş değeri fork():

  • Çocuk sürecinde 0
  • Ebeveyn işleminde çocuğun PID'si
  • Bir başarısızlık varsa ebeveynde -1 (doğal olarak çocuk yoktur)

Test kodunuz doğru çalışıyor; o dönüş değerini saklar fork()içinde child_pidve kullanımları if(bir hata kontrol etmez rağmen) durum 0 olup olmadığını kontrol etmek için


13

Fork () 'in aynı işlemi yarattığını düşündüm, bu yüzden başlangıçta bu programda fork () çağrısının tekrarlı olarak çağrılacağını düşündüm. Ben çatal () oluşturulan yeni işlem çatal () çağrısından sonra başlar sanırım?

Evet. Satırları numaralayalım:

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 */
}

Yürütme akışı:

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

... tam olarak aldığınız çıktıyı açıklar.

Eğer orjinal ve çatallı programın nasıl aynı şekilde davranabileceğini bilmek istiyorsanız, mutlaka aynı şifreyi paylaşıyorlar, Michael Mrozek'in cevabına bakınız .


1 aslında bir talimat olmadığını unutmayın. Ayrıca, orjinali ve çatallı programların aslında aynı anda çalışmadığını unutmayın - ikisinden birinin diğerinin vermesini / önlenmesini beklemesi gerekecektir.
fahişe

1
Çok çekirdekli / çoklu işlemci sistemlerinde, her iki program aslında aynı anda çalışabilir.
jlliagre

@jilliagre Multicore sistemleri gerçekten okuyucuyla ilgili. Çok işlemcili sistemlerde ise, durumun böyle olup olmadığını pratikte bilmiyorum . Bu alanda uzman değilim - ve bu olası bir senaryo gibi görünüyor. İşletim sisteminin aynı anda birden fazla işlemi çalıştırabileceğini kabul edersek (aynı anda eşzamanlılık nasıl olur?), Orijinal program bir CPU'da yönerge 4'ü çalıştırdığı zaman, diğer CPU'ların başka işlemler yürütmekle meşgul olması muhtemeldir .
Kasım’da

Özellikle 5. adımda gerçekleşen bazı G / Ç'lerin altında yatan bir sistem çağrısı olduğu için bunun çok muhtemel bir senaryo olduğunu söyleyebilirim. Bütün CPU'ların meşgul olması, CPU'nun nadiren mevcut makinelerle darboğaz olması nedeniyle sık karşılaşılan bir durum değildir. Görünüşe göre çoklu iş parçacığı ve çok çekirdekli kafa karıştırıcı.
jlliagre

8
Çapraz okların harika olduğunu söylemek için yorum yapabilir miyim ?
JBirch

0

Bunun asıl çözümü

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

-1

hemen sonraki kod ne olursa olsun, fork()çocuk sürecine kopyalanır ve ebeveyn ile çocuk sürecini karıştırmaz, bunlar aynı (çoğaltılmış, paylaşılmayan) ortama sahip iki farklı varlıktır.

Şimdi çıktınızı görün ...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.