Wpis z mikrobloga

Hmm... Mógłby ktoś pomóc to wyjaśnić?

$ cat ./a.c
#include
main()
{
fork();
printf("%d\n",getpid());
fork();
printf("%d\n",getpid());
}

Dlaczego po skompilowaniu i uruchomieniu tego kodu w bashu dostaję 6 wyników, a po przekierowaniu tego gdziekolwiek dostaję 8 wyników?

$ gcc ./a.c
$ ./a.out
5015
5015
5016
5017
5016
5018
$ ./a.out | wc -l
8
$ ./a.out | cat
5064
5064
5066
5066
5064
5067
5066
5068

#jezykc #programowanie #linux
  • 10
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

@Kryspin013: @Kryspin013: fork() kopiuje proces więc jeżeli wpiszesz jedno fork() i jednego prontfa to program wywoła się tak naprawdę 2 razy - dla procesu macierzystego i dla potomnego więc printf zostanie wypisany dwa razy - raz dla macierzystego raz dla potomnego. W przypadku 2 forków wchodzisz w rekurencje:
1) zostaje wywołany pierwszy fork() i wypisuje ci pierwszego prinfa; zostaje stworzony proces potomny
2) zostaje wywołany drugi fork() i wypisuje ci
  • Odpowiedz
@Kryspin013: Strzelam, że bez przekierowania terminal to opóźnia i wchodzisz w problemy zombie, bo nie ma wait_pid czy czegoś tam. A przy przekierowaniu jest to szybsze i przypadkiem nie wchodzisz. Bo główny proces pewnie zdążył już zamknąć deskryptor od stdout, gdy potomne jeszcze próbują do niego pisać.
  • Odpowiedz
@Kryspin013: @ImReally: Faktycznie okrutne. Wydaje mi się że tutaj wyniki będziesz miał w ogóle losowe, niezależnie czy przekierujesz czy nie, czasem printf wykona się więcej razy, czasem mniej. Jest to zapewne związane z tym że po forku masz dwa asynchronicznie działające procesy bez żadnej obsługi xD
  • Odpowiedz
@ImReally: Wydaje mi się że przekierowanie nic do tego nie ma, sprawdziłem na webowym kompilatorze i wyniki są w zasadzie losowe nawet bez przekierowania :)

@Kryspin013: I tak jak Napisał @ImReally powinieneś sprawdzać wynik forka i w ten sposób sterować co ma wykonać który proces.
  • Odpowiedz
@kamil062: @Kryspin013: w przypadku forków nie ma rekurencji i nic nie wpada. Program się dzieli i wykonuje dalej od miejsca podziału.
fork
print1 print2
fork
print1 print12 print2 print22

Wyniki wynikają z różnicy buforowania na terminalu i pipe. Te dwie dodatkowe linie wynikają ze zlepienia z poprzedniego bufora printfa. Wrzuć po każdym printfie fflush(stdout);
  • Odpowiedz
@RRybak: Tak, wiem, ta rekurencja to tak bardziej w cudzysłowie powinno być żeby zrozumieć że program się dzieli :)
Kolejność wygląda mniej więcej tak:
fork()
___
  • Odpowiedz