2010-09-26 5 views
2

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

Правильно ли я это рассматриваю? И может ли кто-нибудь дать мне знать, как я могу это сделать?

+0

У вас нет вызова 'fork()' в вашей примерной программе. Это намеренно? – sth

+0

Отрицательный, просто забыл включить его. – mispecialist

+1

, если wait() находится внутри цикла, он будет последовательно выполнять аргументы. Я думаю, что то, что вы хотите сделать, - это ждать, когда цикл запустит все процессы, выполняющие свою работу. –

ответ

2

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

Короткая версия:

Пожалуйста, сделайте следующие изменения в программе:

1. length = argc;    // in place of length = sizeof(argv); 
2. execl(argv[i],argv[i],0); // in place of execvp(argv[i],0); 
3. #include <unistd.h>   // if you haven't already 

Длинная версия:

(1) переменной length, я предположим, вы хотите получить общее количество аргументов. argv - это pointer-to-char-pointer, и как таковой просто адрес памяти. Если вы распечатаете длину в своей программе, вы заметите, что она всегда 4 (или независимо от размера адреса памяти в вашей системе).

Так что:

length = sizeof(argv); 

Если действительно это:

length = argc; 

argc содержит общее количество аргументов, передаваемых при выполнении процесса. Например,

./a.out /bin/ps /bin/ls 

дает: ARGC = (а не , очень распространенная ошибка)

(2) Еще одна проблема с вашей программой, является execvp вызов.

prototpye для execvp выглядит следующим образом:

int execvp(const char *file, char *const argv[]); 

где ARGV список аргументов, переданных в новую команду, очень похожий на ARGV в вашей собственной программе.

Что вы используете в вашей программе является:

execvp(argv[i],0); 

Пусть i=1 и argv[1] = "/bin/ls". Что это за команда, так это поиск /bin/ls исполняемого файла & передать указатель NULL (0). Это может привести к следующей ошибке во время выполнения:

A NULL argv[0] was passed through an exec system call. 

Ссылаясь на ехес страницы человека,

The first argument, by convention, should point to the filename associated with the file being executed.

Хотя это не обязательно, чтобы передать имя файла еще раз, вы, конечно, не должен передавать указатель NULL , Так как вы не хотите, чтобы передать какие-либо аргументы, я предлагаю вам использовать следующий execl вызов, вместо:

execl(argv[i],argv[i],0); 

Помните, что все такие звонки, наконец, преобразуются в execve() наконец & затем выполняется, что делает их эквивалент в конце концов.

Я рекомендую вам узнать больше о семействе функций exec, используя man.

+0

Спасибо большое, ребята, это мелочи, которые я должен был взять сам: \ Я сейчас выполнил эту программу и отредактирую код выше, чтобы соответствовать окончательной версии. Если вы можете увидеть любые другие ошибки, не стесняйтесь сообщить мне: P – mispecialist

0

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

Не было бы более эффективным использовать потоки для одновременной обработки?

+0

Возможно, но у меня даже меньше опыта с потоками, чем у меня с fork :) – mispecialist

+0

Достаточно честный. Что-то, чтобы взглянуть на некоторое время;) –

0

Я верю, что будет делать то, что вы хотите. Однако ...

fork() действительно не запускают несколько процессов в одной программе. Он запускает несколько копий той же программы в разных процессах. Если между программами нет значительного совпадения, вы можете просто написать отдельно main() s для каждого.

2

Поскольку вы вызываете wait() в цикле, вы будете разветвлять дочерний процесс , и процесс форсирования будет ждать завершения до его вилок следующего. Вам нужно будет разблокировать все дочерние процессы , прежде чем ждать, если вы хотите, чтобы они выполнялись параллельно,

Редактировать: Вы вычисляете длину недействительно. sizeof argv возвращает размер указателя на символ. Этот код

#include <stdio.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) 
{ 
    int pid, i, length; 

    length = argc; 

    for(i = 1; i < length; i++) 
    { 
     printf("Argv[%d]: %s\n", i, argv[i]); //error checking 
     pid = fork(); 

     if(pid < 0) 
     { 
      printf("Fork failed.\n"); 
     }//end if 
     else if(pid == 0) 
     { 
      execvp(argv[i], 0); 
     }//end else if 
     else 
     { 
      printf("Parent process (%d)\n", getpid()); 
     }//end if-else 

    }//end for 
    wait(); 
}//end main 

, кажется, работает хорошо для меня:

datan:~/src/c> ./a.out /bin/ps /bin/ps /bin/ps 
Argv[1]: /bin/ps 
Parent process (12748) 
Argv[2]: /bin/ps 
Parent process (12748) 
Argv[3]: /bin/ps 
Parent process (12748) 
    PID TTY   TIME CMD 
6615 pts/5 00:00:00 bash 
    PID TTY   TIME CMD 
6615 pts/5 00:00:00 bash 
12627 pts/5 00:00:01 emacs 
12748 pts/5 00:00:00 a.out 
12749 pts/5 00:00:00 ps 
12750 pts/5 00:00:00 ps 
12751 pts/5 00:00:00 ps 
datan:~/src/c> 12627 pts/5 00:00:01 emacs 
12749 pts/5 00:00:00 ps 
12750 pts/5 00:00:00 ps 
    PID TTY   TIME CMD 
6615 pts/5 00:00:00 bash 
12627 pts/5 00:00:01 emacs 
12749 pts/5 00:00:00 ps 

(хотя вы, вероятно, следует подождать, пока все дети, не просто, как это делает код).

+0

У меня было ожидание за пределами цикла, чтобы начать с него back out ничего не меняет, за исключением того, что для этого требуется вход пользователя для возврата подсказки. – mispecialist

+0

Я уверен, что ничего не выйдет из команды ls & ps, выполняемой параллельно, это приведет к выходу mish-mashed на консоль. – 2010-09-27 15:52:15

+0

Кроме того, sizeof argv возвращает размер указателя на указатель char, а не указатель на символ. – 2010-09-27 15:57:50

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