Форум программистов, компьютерный форум CyberForum.ru

Параллельный запуск процессов с помощью fork(). Проверить код - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
08.01.2014, 20:03     Параллельный запуск процессов с помощью fork(). Проверить код #1
Правильно ли я накидал параллельный запуск (в данном случае 10 ) процессов с помощью fork() ?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    if(pipe(filedes) == -1) 
    {
        perror("pipe failed");
        exit(EXIT_FAILURE);
    }
    
    for(int i = 0; i < 10; i++)
    {
     pid[i] = fork();
      if (pid[i] != 0)
      {
            // parent
 
           const int bufsize = 512;
           char buf[bufsize];
           bzero(buf, bufsize);
 
           read(filedes[0], buf, bufsize);
 
           printf("Parent:\n");
           printf("%s\n", buf);
          }
      else
      {
           // child
           dup2(filedes[1], STDOUT_FILENO);
           execlp("ls", "ls","-l", NULL); //здесь в дальнейшем будут разные процессы
      }
 
    }
   int status;
   wait(&status);//ожидаю завершение всех процессов
есть сомнения, т.к. на одном из сайтов видел вот такой код для 8ми:
C++
1
2
3
fork();
fork();
fork();
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.01.2014, 20:03     Параллельный запуск процессов с помощью fork(). Проверить код
Посмотрите здесь:

Запуск программы с расширением .сpp с помощью Visual studio 2010 C++
C++ Программирование циклических процессов на языке С++(помогите исправить код)
Параллельный код решения системы C++
Проверить наличие в списке заданного числа с помощью рекурсивной и нерекурсивной функций C++
Как с помощью цикла проверить все вхождения символов? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.01.2014, 20:14     Параллельный запуск процессов с помощью fork(). Проверить код #2
Где в твоем коде запуск потоков?...
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
08.01.2014, 20:15  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #3
Цитата Сообщение от DiffEreD Посмотреть сообщение
Где в твоем коде запуск потоков?...
зачем потоков?? с потоками я уже поработал, мне надо именно процессы. Спасибо
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
08.01.2014, 20:19     Параллельный запуск процессов с помощью fork(). Проверить код #4
Есть несколько моментов, которые смущают.
1. wait ждет изменения статуса одного из дочерних процессов. Следовательно, дождаться всех так просто не выйдет. Нужно что-то вроде сохранения pid всех дочерних процессов и вызов функции waitpid для каждого из них.
2. Проблема - все процессы параллельно пытаются писать в один и тот же канал. При чтении у родительского процесса в результате может получиться каша. Мб имеет смысл создать канал для каждого процесса, а затем мультиплексировать (см select).

Ну и мб стоит озвучить задачу - возможно, она решается чем-нибудь полегче запуска кучи тяжелых процессов.
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
08.01.2014, 20:24  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #5
Цитата Сообщение от 0x10 Посмотреть сообщение
Есть несколько моментов, которые смущают.
1. wait ждет изменения статуса одного из дочерних процессов. Следовательно, дождаться всех так просто не выйдет. Нужно что-то вроде сохранения pid всех дочерних процессов и вызов функции waitpid для каждого из них.
2. Проблема - все процессы параллельно пытаются писать в один и тот же канал. При чтении у родительского процесса в результате может получиться каша. Мб имеет смысл создать канал для каждого процесса, а затем мультиплексировать (см select).

Ну и мб стоит озвучить задачу - возможно, она решается чем-нибудь полегче запуска кучи тяжелых процессов.
да задача такая: запустить десяток процессов именно параллельно, потом дождаться завершения всех процессов(в данном случае ls, а по заданию разные названия их считываются из файла - это я сделал) при это через pipe родительский процесс (который ожидает завершения всех) должен получить информацию из потока вывода процесса и потока ошибок (в том порядке в котором они будут завершаться т.е. порядок каждый раз разный).
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
08.01.2014, 20:27     Параллельный запуск процессов с помощью fork(). Проверить код #6
Ну можно в принципе повесить обработчик на SIGCHILD и там уже определять какой процесс завершился, и только в этом случае читать из соответствующего ему канала, если требуется сохранить порядок...
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
09.01.2014, 14:14  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #7
Цитата Сообщение от 0x10 Посмотреть сообщение
Ну можно в принципе повесить обработчик на SIGCHILD и там уже определять какой процесс завершился, и только в этом случае читать из соответствующего ему канала, если требуется сохранить порядок...
дак всё же, если запускать процессы таким образом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
pid_t pid[10];
pid[0] = fork();
if(pid[0] == 0)
{}
else {}
pid[1] = fork();
if(pid[1] == 0)
{}
else {}
pid[2] = fork();
if(pid[2] == 0)
{}
else {}
они будут работать "параллельно" или нет?
и второе, имеется вот такая привязка:
C++
1
2
 signal (SIGCHLD, sig_chld); //привязка конкректного 
//сигнала к функция обработки сигнала
вот функция обработки сигнала
C++
1
2
3
4
5
6
7
void sig_chld(int signo){
    pid_t pid;
    int stat;
    while( ( pid = waitpid(-1, &stat, WNOHANG) ) > 0 ){
 
    }
}
что надо подавать в качестве параметра(int signo) в функцию? и правильно ли написан обработчик? можно ли уже после while получать данные с дочернего процесса через pipe? Заранее спасибо
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 15:57     Параллельный запуск процессов с помощью fork(). Проверить код #8
Цитата Сообщение от танкист34 Посмотреть сообщение
дак всё же, если запускать процессы таким образом:
Будут выполняться параллельно, только не нужно полностью писать такую портянку - т.е. достаточно все записать в один цикл, как и было предложено изначально.

Цитата Сообщение от танкист34 Посмотреть сообщение
что надо подавать в качестве параметра(int signo) в функцию?
В обработчик сигнала самому ничего передвать не нужно. Когда он будет вызван, в качестве аргумента будет передано значение пойманного сигнала. Может быть использовано, например если один обработчик назначается нескольким сигналам.

Цитата Сообщение от танкист34 Посмотреть сообщение
и правильно ли написан обработчик?
Вроде ничего криминального не вижу. Т.е. определим pid всех процессов, состояние которых изменилось, и уже в самом теле цикла можно будет получать данные.

Теперь важное: опровергаю свои же слова. Я не уверен насколько корректно читать из канала только в конце. Т.е. между записью и чтением данные должны храниться в каком-то буфере, не думаю, что он резиновый.

Если вечером буду не слишком упоротый, попробую набросать пример.

Добавлено через 11 минут
Собственно, размер буфера канала:
Bash
1
2
3
4
$ ulimit -a
...
pipe size            (512 bytes, -p) 8
...
Добавлено через 2 минуты
Ну как я понимаю, это обычная лаба, поэтому можно не заморачиваться, пусть просто работает как задумывалось изначально.
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
09.01.2014, 16:11  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #9
0x10, спасибо большое=)) может быть и стоит считывать данные в цикле while? получается обнаруживается завершившийся потомок->он что-то записал в pipe, а когда в while вызовешь функцию на чтение из пайпа, то писать следующий потомок уже не сможет туда->пока родитель не считает, дочерние блокируются.
Я просто уже как-то раз применял read и write и действительно они инхронизируют чтение-запись.
Просто вот я не знаю для всех ли дочерних процессов будет один только родитель, по мне вроде как да, тогда способ должен сработать.
Но проблема возникает ещё в том, что при запуске данных из потока ошибок процесса программа не завершается, а как бы уходит в бесконечный цикл. И есть сомнения по поводу того, всегда ли в поток ошибок что-то пишется, если процесс завершился нормально или нет.

Добавлено через 1 минуту
Цитата Сообщение от 0x10 Посмотреть сообщение
Ну как я понимаю, это обычная лаба, поэтому можно не заморачиваться, пусть просто работает как задумывалось изначально.
нет, это не лаба, это задание на защиту лабы(дополнительный вопрос)

Добавлено через 3 минуты
Цитата Сообщение от 0x10 Посмотреть сообщение
pipe size (512 bytes, -p) 8
а что это даёт? размер pipe не больше 512 или 512*8?
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 16:13     Параллельный запуск процессов с помощью fork(). Проверить код #10
Цитата Сообщение от танкист34 Посмотреть сообщение
получается обнаруживается завершившийся потомок->он что-то записал в pipe, а когда в while вызовешь функцию на чтение из пайпа, то писать следующий потомок уже не сможет туда->пока родитель не считает, дочерние блокируются.
Ограничиваться одним каналом для всех процессов не стоит.
Может получиться ситуация, когда сначала один процесс записал порцию данных, потом второй что-то записал туда же. Как при чтении из канала разделять?

Добавлено через 2 минуты
Цитата Сообщение от танкист34 Посмотреть сообщение
а что это даёт? размер pipe не больше 512 или 512*8?
Стандартный лимит на буфер канала - 4096 байт. Его можно увеличить, но на это может не быть прав.

Предлагаю не заморачиваться. Тем более если это всего лишь доп. задание.
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
09.01.2014, 16:16  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #11
Цитата Сообщение от 0x10 Посмотреть сообщение
Может получиться ситуация, когда сначала один процесс записал порцию данных, потом второй что-то записал туда же. Как при чтении из канала разделять?
ну просто если он записал, значит, он завершился я так понимаю, следовательно, считываем read ом, а когда read работает по идее писать в pipe никто не должен

Добавлено через 1 минуту
Цитата Сообщение от 0x10 Посмотреть сообщение
Предлагаю не заморачиваться. Тем более если это всего лишь доп. задание.
не заморачиваться это как? создать pipe на 4096 и писать туда? а потом по окончании всех предков считать?
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 17:49     Параллельный запуск процессов с помощью fork(). Проверить код #12
Цитата Сообщение от танкист34 Посмотреть сообщение
ну просто если он записал, значит, он завершился
Процесс может писать много, и запись производится не один раз в конце, а по ходу выполнения.

Цитата Сообщение от танкист34 Посмотреть сообщение
не заморачиваться это как?
Как и было сказано в начале: по одному каналу на каждый дочений процесс (грубо говоря), считывать только после завершения процесса.
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
09.01.2014, 18:14  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #13
я вот так вот считываю с файла имена процессов, а потом делаю указатели типа char, чтобы использовать их при вызове, например, ls через execlp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  //получение имён процессов из файла
    std::ifstream file("proc_name.txt");
    std::string str[10];
    int k = 0;
    while(file) {
      std::getline(file, str[k]);
      k++;
    }
    //получен массив с названиями процессов из файла
    //перевод названий процессов в массив char
    char mass[10][10];
    for(int i = 0; i < 10; i++)
    {
        strcpy(mass[i], str[i].c_str() ); 
    }
    char *p[10]; //массив указателей на строки
    for(int i = 0; i < 10; i++)
    {
        p[i] = mass[i];
    }
но когда подсовываешь указатель вот так:
C++
1
execl(p[0], p[0], NULL);
процесс не запускается, я думаю что что-то с путём не то, так как если исправить на
C++
1
execl(/bin/ls, p[0], NULL);
, то всё работает, как быть? ведь я изначально не знаю какой процесс (название его) будет на первом месте в файле
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 18:24     Параллельный запуск процессов с помощью fork(). Проверить код #14
1. Как выглядит содержимое файла?
2. Я понимаю, что тут раздел плюсовый, но насколько я знаю, линуксовые лабы зачастую пишутся на чистых сях. У вас нет такого условия?

Добавлено через 49 секунд
3. Можно проверять возвращаемое значение exec и выводить сообщение об ошибке - будет понятно без телепатов.

Добавлено через 6 минут
4. Чтение сначала в string, потом копирование в массив... Нет, это определенно слишком мутно.
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
09.01.2014, 18:44  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #15
Цитата Сообщение от 0x10 Посмотреть сообщение
но насколько я знаю, линуксовые лабы зачастую пишутся на чистых сях. У вас нет такого условия?
нет, ограничения нет, g++ стоит
файл вот такого вида
ls
date
arch
.
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 18:49     Параллельный запуск процессов с помощью fork(). Проверить код #16
Ну как бы вот. execl не ищет исполняемые файлы в PATH, а требует полных путей. См функции, где в названии есть буква p - execlp, execvp.
танкист34
-62 / 0 / 0
Регистрация: 15.03.2013
Сообщений: 328
09.01.2014, 19:05  [ТС]     Параллельный запуск процессов с помощью fork(). Проверить код #17
Цитата Сообщение от 0x10 Посмотреть сообщение
Ну как бы вот. execl не ищет исполняемые файлы в PATH, а требует полных путей. См функции, где в названии есть буква p - execlp, execvp.
я их тоже пробывал, такая же петрушка, не запускаются и всё если на первом месте указатель=))
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 19:09     Параллельный запуск процессов с помощью fork(). Проверить код #18
Еще раз: посмотри сообщение об ошибке. man perror
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.01.2014, 20:03     Параллельный запуск процессов с помощью fork(). Проверить код
Еще ссылки по теме:

C++ проверить код на с++
Проверить список запущенных процессов на наличие нужного C++
C++ Проверить делится ли число нацело с помощью машины тьюринга

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
09.01.2014, 20:03     Параллельный запуск процессов с помощью fork(). Проверить код #19
Понятно, что этот этап уже пройден, но все-таки приложу упрощенный пример того, что требуется в исходном задании. Весь прочий обвес в виде перенаправления stderr, чтения списка процессов из файла и т д - по желанию, самостоятельно.

В примере запускаются процессы, каждый из которых спит i секунд.
Вложения
Тип файла: zip run10.zip (2.0 Кб, 16 просмотров)
Yandex
Объявления
09.01.2014, 20:03     Параллельный запуск процессов с помощью fork(). Проверить код
Ответ Создать тему
Опции темы

Текущее время: 07:47. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru