2017-02-16 17 views
0

Я пытаюсь создать программу для создания нескольких процессов, каждая из которых читает строку из консоли, а затем делайте что-то с ней. У меня возникают проблемы с getline(cin, temp), только иногда читая строку. Входной буфер уже загружен 4 строками текста.C++ Getline не всегда получает строку в нескольких разветвленных процессах в Linux

EDIT: Мне нужно использовать fork, который создает несколько процессов (а не потоков), чтобы использовать wait, который ждет завершения первого дочернего процесса, а затем продолжит.

#include <iostream> 
#include <iostream> 
#include <string> 
#include <cstring> 
#include <sstream> 
#include <unistd.h> 
#include <sys/wait.h> 

using namespace std; 

int childprog(); 

int main() 
{ 

    pid_t childpid; 

    for (int i = 0; i < 4; ++i) 
    { 
     if ((childpid = fork()) == 0) //Child process 
     { 
      childprog(); 
      return 0; 
     } 
    } 

    if (childpid != 0) //If Parent 
    { 
     wait(0); 
     //Stuff 
     return 0; 
    } 
} 

int childprog() 
{ 
    string temp; 
    getline(cin, temp); 
    cout << temp << endl; //Actually do other stuff, just here for debugging 
    return 0; 
} 

В то время как он должен распечатать:

string number one 
string number two 
string number three 
string number four 

Он печатает:

string number one 

string number two 
string number three 

или

(blank line) 
string number one 

string number two 

с пустыми строками в любом из возможных положений.

Спасибо за помощь!

+0

Можете ли вы предоставить [MCVE], пожалуйста? –

+0

OK, сделано. Программа полностью runable @ πάνταῥεῖ – DDriggs00

ответ

0

Я нашел решение после того, как @JasonLang опубликовал свой ответ, сообщив мне, что это проблема доступа. Я скорректировал его, просто перемещая показание входного буфера до fork(), гарантируя, что только один процесс попытается прочитать его сразу.

я заменил это:

for (int i = 0; i < 4; ++i) 
{ 
    if ((childpid = fork()) == 0) //Child process 
    { 
     childprog(); 
     return 0; 
    } 
} 

с этим:

string temp; 
for (int i = 0; i < 4; ++i) 
{ 
    getline(cin, temp); 
    if ((childpid = fork()) == 0) //Child process 
    { 
     childprog(temp); 
     return 0; 
    } 
} 

и это:

int childprog() 
{ 
    string temp; 
    getline(cin, temp); 
    cout << temp << endl; //Actually do other stuff, just here for debugging 
    return 0; 
} 

с этим:

int childprog(string input) 
{ 
    cout << input << endl; //Actually do other stuff, just here for debugging 
    return 0; 
} 
0

Проблема в том, что каждый поток обращается к общему ресурсу: getline и входному буферу. Некоторые операции являются атомарными, а другие могут быть прерваны.

Это означает, что точное время операций может мешать друг другу. Например, два потока проверяют, какая строка находится рядом с чтением, они оба получают одну и ту же строку. Затем это «условие гонки», чтобы увидеть, какие из них читают его сначала, а другой поток получает пустую строку.

Вам нужно как-то заблокировать getline, чтобы каждый поток мог прочитать строку до того, как другие прокрались внутрь и попытались взять некоторые данные. Еще лучшее решение - просто избежать двух процессов, связанных с одними и теми же данными, но если вы не можете этого сделать, вы можете использовать Mutex.

http://www.thegeekstuff.com/2012/05/c-mutex-examples/

разобранный пример того, как используется мьютекс:

#include<pthread.h> 
#include<unistd.h> 

pthread_mutex_t lock; 

int childprog() 
{ 
    // Put the mutex lock and unlock around the minimum amount of code  
    // which needs to be an "atomic operation". While "locked" other 
    // threads won't run this bit of code, so keep it brief. However, 
    // Locking and unlocking is itself an expensive operation, so you 
    // should be careful to minimize the number of times it happens 

    string temp; 

    pthread_mutex_lock(&lock); 
    getline(cin, temp); 
    pthread_mutex_unlock(&lock); 

    cout << temp << endl; 

    return 0; 
} 

// the rest of your program here 

Однако обратите внимание, что есть также линия необходимо инициализировать семафор, прежде чем вы использовали его

pthread_mutex_init(&lock, NULL) 

И связанный пример использует pthread create, а не fork

+0

Мне нужно использовать 'wait', который не работает с потоками, а только отдельные процессы. Mutex работает только с потоками, поскольку процессы выполняются в отдельных пространствах памяти. – DDriggs00

 Смежные вопросы

  • Нет связанных вопросов^_^