2016-02-04 2 views
3

У меня есть эта программа на C++.Работа fork() в C++

#include <iostream> 
#include <unistd.h> 
#include <sys/types.h> 


using namespace std; 

int main() 
{ 
    cout<<"*\n"; 
    fork(); 
    cout<<"A\n"; 
    fork(); 
    cout<<"B\n"; 
    fork(); 
    cout<<"C\n"; 
    return 0; 
} 

Выход:

* 
A 
B 
C 
* 
A 
B 
C 

Я думаю, что это должно быть:

* 
A 
B 
C 
A 
B 
C 
B 
C 
C 

Объяснение: '*' должен быть отпечатанные на одном процессе. Теперь, после fork() 2 'A' должно быть напечатано и сыном для 'B' & 'C'.

Link to code

+0

Я бы ожидал * A B C * A B C * A B C * A B C * A B C * A B C * A B C * A B C из-за буферизации. – immibis

+3

Это неопределенно. Если вам нужен конкретный заказ, вам нужно использовать детерминированные методы, а не многопроцессорную обработку. И поведение определяется операционной системой, а не C++. – EJP

+0

Я не могу воспроизвести ваши результаты с помощью g ++ или clang ++ локально. Какой компилятор вы использовали, и на какой операционной системе?Я получил 1 *, 2 A, 4 B и 8 C, чего вы должны ожидать _actually_, так как каждый fork() разбивает процесс на два. – TBBle

ответ

1

На основе замечаний по этому вопросу, ответ в том, что fork в ideone.com онлайна компилятора просто ограничивая вас один экземпляр вашего процесса, и буферный свой выход.

Update: На самом деле, это также лежа: http://ideone.com/oXqqwM показывает, что fork() претендует на успех, но только первый создает новую копию процесса.

Я подозреваю, что если вы проверили возвращенные значения fork() вы бы получить некоторые подсказки, как к удивительному поведению, что вы видите - все, кроме первого будет возвращено -1 - и если вы использовали std::endl вместо вас мог избегать первого *.

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

Так что ожидайте 1 или более «*», 2 или более «A», 4 или более «B» или 8 или более «C», за исключением того, что если fork() терпит неудачу, номера будут закрыты.

Ваше ожидание 1 «*», 2 «А», 3 «Б» и 4 «C» указывает на то, что вы упускать из виду, что оба процессы, выходящие из fork() выйдет следующий fork(), поэтому вы дважды, а не увеличивать на единицу.

+0

Примечание. Отредактировано после принятия, но я не думаю, что это проблема. – TBBle

0

так ... если вы получаете больше, чем один * то есть что-то странное происходит, и я подозреваю, что это зависит от конкретной реализации ... fork даст каждому из ребенка обрабатывает копия файловых дескрипторов, включая stdout ... поэтому в вашей реализации он также получает действительную копию потока std :: cout ... у которого уже есть буфер, загруженный * ...

Я думаю, что если вы меняете свою программу, чтобы включить флеш, вы увидите то же самое, что и я:

#include <iostream> 
#include <unistd.h> 
#include <sys/types.h> 


using namespace std; 

int main() 
{ 
    cout<< "*\n"; 
    flush(cout); 
    fork(); 
    cout<<"A\n"; 
    flush(cout); 
    fork(); 
    cout<<"B\n"; 
    flush(cout); 
    fork(); 
    cout<<"C\n"; 
    flush(cout); 
    return 0; 
} 
+0

Нет, 'flush()' недостаточно. Чтобы гарантировать что-либо о заказе в этой программе, вам понадобится какая-то межпроцессная связь. – duskwuff

+2

Он будет останавливать несколько '' 's, хотя. –

+0

Flushing не покупает вам заказы, но, как говорится в ответе, он должен избавиться от ложных дубликатов символов. – 5gon12eder