LINUX.ORG.RU

fork() again...


0

0

Здравствуйте. Я так и не смог побороть свою проблему с форком, и после запуска небольшой тестовой проги понял, что я вообще не в теме про форк(). Если можете, объясните плз почему программа работает именно так:

$ cat test.c #include <stdio.h>

void do_(void) { int i;

puts("do called"); for(i=0; i<3; i++) { if (!fork()) puts("do child fork()"); else puts("do father fork()"); } }

int main(void) { if (fork()) exit(0); if (freopen("out.txt", "w", stdout) == NULL) { perror("Unable to open log file"); return 9; } puts("main child fork"); puts("reopened"); do_(); }

$ gcc -o test test.c $ ./test $ cat out.txt main child fork reopened do called do child fork() do child fork() do father fork() main child fork reopened do called do father fork() do father fork() do child fork() main child fork reopened do called do child fork() do father fork() do child fork() main child fork reopened do called do child fork() do child fork() do child fork() main child fork reopened do called do father fork() do child fork() do child fork() main child fork reopened do called do father fork() do father fork() do father fork() main child fork reopened do called do child fork() do father fork() do father fork() main child fork reopened do called do father fork() do child fork() do father fork()

Ну если здесь для вас все понятно, то у меня возникли следующие вопросы: 1. почему не совпадает количество сообщений "do child fork()" и "do father fork()" 2. почему сообщения "main child fork" и "reopened" выводятся несколько раз? (т.е. функция main выполянется с начала не один раз). Да, я не очень хороший программер - про форк знаю только то, что она создает копию текущего процесса, но откуда начинается выполнение я не знаю. Насколько корректна данная схема ? Заранее спасибо за помощь.

anonymous

вот бы увидеть нормальное форматирование ;)

pisun
()

Здравствуйте. Я так и не смог побороть свою проблему с форком, и 
после запуска небольшой тестовой проги понял, что я вообще не в теме
 про форк(). Если можете, объясните плз почему программа работает 
именно так:

$ cat test.c #include <stdio.h>

void do_(void) { 
 int i;
 puts("do called"); 
 for(i=0; i<3; i++) { 
 if (!fork()) puts("do child fork()"); 
 else puts("do father fork()"); 
} 
}

int main(void) { 
 if (fork()) exit(0); 
 if (freopen("out.txt", "w", stdout) == NULL) { 
  perror("Unable to open log file"); return 9; 
} 
 puts("main child fork"); 
 puts("reopened"); 
 do_(); 
}

$ gcc -o test test.c 
$ ./test 
$ cat out.txt
main child fork 
reopened 
do called 
do child fork() 
do child fork() 
do father fork() 
main child fork 
reopened 
do called 
do father fork() 
do father fork() 
do child fork() 
main child fork 
reopened 
do called 
do child fork() 
do father fork() 
do child fork() 
main child fork 
reopened do called 
do child fork() 
do child fork() 
do child fork() 
main child fork 
reopened do called
do father fork() 
do child fork() 
do child fork() 
main child fork 
reopened 
do called 
do father fork() 
do father fork() 
do father fork() 
main child fork 
reopened 
do called 
do child fork() 
do father fork() 
do father fork() 
main child fork 
reopened do called 
do father fork() 
do child fork() 
do father fork()

Ну если здесь для вас все понятно, то у меня возникли следующие 
вопросы: 
1. почему не совпадает количество сообщений "do child fork()" и 
"do father fork()" 
2. почему сообщения "main child fork" и "reopened"
 выводятся несколько раз? (т.е. функция main выполянется с начала не 
один раз). Да, я не очень хороший программер - про форк знаю только
 то, что она создает копию текущего процесса, но откуда начинается 
выполнение я не знаю. Насколько корректна данная схема ? Заранее 
спасибо за помощь.

anonymous
()
Ответ на: комментарий от anonymous

Как я понял, дочерний процесс начинает выполняться с вызова fork() ? Тогда вовсе непонятно то, о чем я спросил в 2 вопросе..

anonymous
()
Ответ на: комментарий от anonymous

Я не знаю, тебе ли раньше объясняли про fflush и т.д...

В общем, потоковый вывод (printf, puts и т.д.) и т.д. работает через буфер. Сообщения помещаются в промежуточный буфер, а потом по определенному условию выводятся в файл. Если делать fork, то дочерний процесс получит копию этого буфера и потом выведет его содержимое...

В общем, если ты добавишь строку

setvbuf(stdout, NULL, _IONBF, 0);

перед

puts("main child fork");

вся "мистика" исчезнет :))

mky ★★★★★
()
Ответ на: комментарий от anonymous

int main(void) { 
 if (fork()) exit(0); 

"Правильно" у каждого своё.
Моё "правильно", например, не может быть как-либо связано с программой с таким началом. 

Советую почитать
man 2 wait



anonymous
()
Ответ на: комментарий от anonymous

> Я перенаправляю потоки freopen(). Пойдет ?

Да.

Только надо закрыть stdin, перенаправить stderr и еше setsid сделать.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Спасибо. stderr тоже перенаправляю. а зачем делать setsid ? для чего нужно создавать новую сессию?

anonymous
()
Ответ на: комментарий от anonymous

> для чего нужно создавать новую сессию?

Чтобы не ловить сигналы, посланные оболочкой (и некоторыми злобными системными программами типа pppd) всей сессии.

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.