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
@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
@VukoPL: @kamil062: Dobra, żeby nie było:

#include
main()
{
if(fork()==0)
printf("%d\n",getpid());
if(fork()==0)
printf("%d\n",getpid());
}

Kolejne zadanie zadanie z egzaminu - wyniki różne w zależności czy się przekieruje go gdzieś potokiem lub strumieniem czy nie. Innymi slowy shell -> 3 wyniki, potok, strumień --> 4 wyniki. Kompilatory online w moim przypadku nie zwracały losowych wyników tylko w (dla tego kodu) 4 wyniki tak jak przy przekierowaniu (dla poprzedniego kodu 8 wyników).
  • 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()
___printf()
__fork()
______printf()
__printf()
printf()
fork()
___printf()
printf()
  • Odpowiedz