Всем доброго времени суток!Короче это я пытаюсь сделать "процесный движок", софтина должна рождать потомков в количесвеMAXPROC, они засыпают на random() % 100, как только кто нить из потомков заканчивает работу, родитель запускает еще одного потомка, что бы потомков всегда было заданное количество.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <error.h>
#define MAXPROC 4
main()
{
int pc = MAXPROC;
int pid = 0;
int ppid = getpid();
srand(time(NULL));
while(1) {
if(ppid == getpid() && pc > 0) {
pc--;
pid = fork();
printf("(process count %d) PID:%d\n",pc, pid);
} else {
printf("PPID: %d\t PID: %d PC: %d\n", ppid, getpid(), pc);
pc = 0;
}
switch(pid) {
case 0:
printf("Child PID: %d\n", getpid());
sleep(random() % 100);
break;
case -1:
perror("fork()\n");
exit(1);
default:
if(pc == 0) {
printf("Parent waiting for child with PID %d\n", pid);
wait();
pc++;
}
break;
}
}
}Работает ли это так как мне надо? Если нет, то почему? И как отлаживать такие приложения?
>Работает ли это так как мне надо? Если нет, то почему? И
>как отлаживать такие приложения?Дочерние процессы не выходят, а снова попадают в while(1) и ведут себя сами как родители. Поздравляю, fork-бомба готова!
>>Работает ли это так как мне надо? Если нет, то почему? И
>>как отлаживать такие приложения?
>
>Дочерние процессы не выходят, а снова попадают в while(1) и ведут себя
>сами как родители. Поздравляю, fork-бомба готова!Ну не совсем так...
там проверочка на чилда, если чилд то каунтер процесов обнуляеться...
читай пожалуйста внимательно
>Ну не совсем так...
> там проверочка на чилда, если чилд то каунтер процесов обнуляеться...
> читай пожалуйста внимательноИзвиняюсь, я немного запутался. По-моему, код работает немного неочевидно, и я бы его переписал так:
int child_func()
{
...
}int main()
{
int child_count = 0;
pid_t pid;
while(1)
{
while(child_count < MAXCHILDREN)
{
if(pid = fork())
{
/* проверяем ошибки */
child_count++;
}
else
{
child_func();
exit(0);
}
}
while(pid == wait(NULL))
{
/* для каждого завершенного потомка уменьшаем child_count */
}
}
}
Согласен так логичнее выглядит,
только while(pid == wait(NULL)) ждет только одного потомка и потом стартует тоже только одного.
Интересно которого?
>>Работает ли это так как мне надо? Если нет, то почему? И
>>как отлаживать такие приложения?
>
>Дочерние процессы не выходят, а снова попадают в while(1) и ведут себя
>сами как родители. Поздравляю, fork-бомба готова!нет, там условие:
if(ppid == getpid() && pc > 0) {
т.е. дети не будут форкаться
>Работает ли это так как мне надо? Если нет, то почему?Мы не телепаты и не знаем что тебе надо :)
Данный код делает несколько форков и в них спит.> И как отлаживать такие приложения?
Тщательно и с применением всех доступных средств :)
Хотя что там отлаживать-то, он че падает или делает не то что ожидается?
>>Работает ли это так как мне надо? Если нет, то почему?
>
>Мы не телепаты и не знаем что тебе надо :)
>Данный код делает несколько форков и в них спит.
>
>> И как отлаживать такие приложения?
>
>Тщательно и с применением всех доступных средств :)
>Хотя что там отлаживать-то, он че падает или делает не то что
>ожидается?Всегда должно быть количесвто потомков равное.
По порядку,
Рождаеться MAXPROC потомков,
допустим один засыпает на 20сек и второй 60сек и тд
Просыпаеться первый черз 20сек и заверщает работу
надо что бы родитель пускал еще одного вместо него
>[оверквотинг удален]
>>Тщательно и с применением всех доступных средств :)
>>Хотя что там отлаживать-то, он че падает или делает не то что
>>ожидается?
>
>Всегда должно быть количесвто потомков равное.
>По порядку,
>Рождаеться MAXPROC потомков,
>допустим один засыпает на 20сек и второй 60сек и тд
>Просыпаеться первый черз 20сек и заверщает работу
>надо что бы родитель пускал еще одного вместо негоПроснувшись потомок идет на while(1), т.е. не завершается.
>[оверквотинг удален]
>>>ожидается?
>>
>>Всегда должно быть количесвто потомков равное.
>>По порядку,
>>Рождаеться MAXPROC потомков,
>>допустим один засыпает на 20сек и второй 60сек и тд
>>Просыпаеться первый черз 20сек и заверщает работу
>>надо что бы родитель пускал еще одного вместо него
>
>Проснувшись потомок идет на while(1), т.е. не завершается.ага уже понял )
>[оверквотинг удален]
>>>ожидается?
>>
>>Всегда должно быть количесвто потомков равное.
>>По порядку,
>>Рождаеться MAXPROC потомков,
>>допустим один засыпает на 20сек и второй 60сек и тд
>>Просыпаеться первый черз 20сек и заверщает работу
>>надо что бы родитель пускал еще одного вместо него
>
>Проснувшись потомок идет на while(1), т.е. не завершается.И сразу же вопрос, зачем породив N процессов делать завершение и новый форк для них? Не лучше ли если процесс выполнив задачу просто снова засыпает?
>[оверквотинг удален]
>>>Рождаеться MAXPROC потомков,
>>>допустим один засыпает на 20сек и второй 60сек и тд
>>>Просыпаеться первый черз 20сек и заверщает работу
>>>надо что бы родитель пускал еще одного вместо него
>>
>>Проснувшись потомок идет на while(1), т.е. не завершается.
>
>И сразу же вопрос, зачем породив N процессов делать завершение и новый
>форк для них? Не лучше ли если процесс выполнив задачу просто
>снова засыпает?Задумка такая ) некя чилд функция получает в качестве параметра элемент структуры, производит с ней операции и завершае работу, след аналогично. Что бы обработка элементов не повторялась, нечто похожее на такой способ синхронзации. Може есть другие варианты.. я не давно занимаюсь программированием.
>>[оверквотинг удален]
>Задумка такая ) некя чилд функция получает в качестве параметра элемент структуры,
>производит с ней операции и завершае работу, след аналогично. Что бы
>обработка элементов не повторялась, нечто похожее на такой способ синхронзации. Може
>есть другие варианты.. я не давно занимаюсь программированием.вопрос 1: нужны ли тебе тут вообще процессы, может проще взять потоки? Для ОС легче их создавать. вопрос 2: зачем тебе каждый раз перезапускать процесс,может ему проще получать данные используя какойнить shared memory or pipes?
поразмысль над этим
> И как отлаживать такие приложения?А отлаживать - syslog()'ом (man 3 syslog). И печатать timestamps с точностью до микросекунды. (Чем и я сам сейчас, кстати, и занимаюсь :) )
Have fun!
elvenic.
В итоге поучилось нечто такое, если где то есть ошибка сообщите. Всем спасибо за участие.#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define MAXPROC 4 /* Максимальное количество процессов*/
#define WTIME 30 /* Время работы процесса максимальное*/main()
{
pid_t pid = 0; /* PID процесса потомка*/
pid_t cpid = getpid(); /* PID родителя всех потомков в данном процессе */
unsigned status = 0;
srand(time(NULL));
unsigned char child_proc_count = 0;
while(1) {
if(cpid == getpid() && child_proc_count < MAXPROC ) { /* Если этот процесс первый */
child_proc_count++; /* Увеличиваем счетчик потомков*/
pid = fork(); /* Рождение потомка */
}
switch(pid) {
case 0: /* Код потомка */
printf("Пороцесс потомок PID=%d\n", getpid());
sleep(random() % WTIME); /* Полезная работа потомка*/
exit(status); /* Окончание работы потомка со статусом 0 */
break;
default:
if(child_proc_count == (MAXPROC - 1)) {
/* Ожидае пока потомок закончит работу со статусом 0 */
printf("Запущенно потомков - %d\n Ждем окончание работы потомка PID=%d\n", child_proc_count, wait(&status));
child_proc_count--; /* Уменьшаем количество потомков */
}
break;
}
}}
>В итоге поучилось нечто такое, если где то есть ошибка сообщите. Всем
>спасибо за участие.Извиняюсь за наглость в этом посте, я просто написал всё что я думаю об этом коде, я не хочу вас обидеть ни в коей мере.
Я уже показал как обычно делаются такие вещи в предыдущем посте. А именно:
if(pid == fork())
{
это родитель, проверяем ошибки
}
else
{
это потомок, делаем работу и обязательно выходим!
}Вот эта конструкция является идиомой в программировании, её умеют "увидеть" сотни и тысячи программистов. Облегчите поддержку вашего кода :)
В вашем коде:
if(cpid == getpid() && child_proc_count < MAXPROC ) { /* Если этот процесс первый */
вот эту строку я сначала без комментария вообще не понял, и поэтому неправильно сказал что это форк-бомба, за что мне очень стыдно. К тому же, при каждом шаге цикла вызывается getpid(), без которого можно обойтись (в моём коде его нет)child_proc_count++; /* Увеличиваем счетчик потомков*/
нелогично, в этот момент потомка ещё нет и неизвестно -- может даже не хватит памяти его создатьpid = fork(); /* Рождение потомка */
см. выше насчёт идиомы программированияswitch из 0 и default это эффективно является тем же if() что и в идиоме, только это снова неочевидно
printf("Запущенно потомков - %d\n Ждем окончание работы потомка PID=%d\n", child_proc_count, wait(&status));
вынесите wait() в отдельную строку и сделайте проверку ошибок. логически (с первого взгляда) эта строка кода выводит текст, а реально -- ждёт потомка и только потом выводит текст. (фактически, изменяется способ исполнения программы -- она засыпает, нужно это подчеркнуть)
Я бы всё-таки написал:switch(pid = fork())
{ case -1: /* ошибка */
...
break;
case 0: /* дочерний процесс */
...
exit(...);
default: /* родитель */
...
break;
}И у вас тут опечатка: "if(pid == fork())"
>[оверквотинг удален]
>см. выше насчёт идиомы программирования
>
>switch из 0 и default это эффективно является тем же if() что
>и в идиоме, только это снова неочевидно
>
>printf("Запущенно потомков - %d\n Ждем окончание работы потомка PID=%d\n", child_proc_count, wait(&status));
>вынесите wait() в отдельную строку и сделайте проверку ошибок. логически (с
>первого взгляда) эта строка кода выводит текст, а реально -- ждёт
>потомка и только потом выводит текст. (фактически, изменяется способ исполнения программы
>-- она засыпает, нужно это подчеркнуть)Действительн, огромное спасибо за полезные комментарии, я не очень давно программирую на Си :-) и с удовольствием приму Ваши комментарии к сведению, и поступлю в соответсвии с ними. У самого голова пухнет от чтения чужих кодов... В любом случае это еще не оконченный продукт и в данном виде, так сказать, существует только на бумаге и ввиде учебного примера(для меня же :-). А в общем, очень рад на такую реакцию знаменитого сообщества ) Большое вам спасибо, Вашими стараниями и из меня получиться хороший программист!
PS Так настроение поднял сутра )
[...]
>#include <stdio.h>
>#include <stdlib.h>
>#include <time.h>
>#include <error.h>[...]
error.h тут лишний.
Также нехватает нескольких хедеров:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
>error.h тут лишний.Наверное, имелось ввиду errno.h.
>>error.h тут лишний.
>
>Наверное, имелось ввиду errno.h.Даже если и так -- errno.h был бы тоже лишним :)
>>error.h тут лишний.
>
>Наверное, имелось ввиду errno.h.А в чем разница?
У Б. Моли в "Unix/Linux. Теория и практика программирования."
perror() применяеться ваапсче без подключения ни errno.h ни error.h )
у меня компилер ругаеться если я их не включаю и использую что то из этих фалов, хотя собирает и работает )
>>>error.h тут лишний.
>>
>>Наверное, имелось ввиду errno.h.
>
>А в чем разница?man 3 errno
man 3 error>У Б. Моли в "Unix/Linux. Теория и практика программирования."
> perror() применяеться ваапсче без подключения ни errno.h ни error.h )У меня в man'е написано, что perror() находится в stdio.h
>[оверквотинг удален]
>>
>>А в чем разница?
>
>man 3 errno
>man 3 error
>
>>У Б. Моли в "Unix/Linux. Теория и практика программирования."
>> perror() применяеться ваапсче без подключения ни errno.h ни error.h )
>
>У меня в man'е написано, что perror() находится в stdio.hа какой пакет поставить? у меня таких man'ов нет...
tigo@box:~/proj$ cat /etc/debian_version
4.0
tigo@box:~/proj$ uname -a
Linux box 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux
Установка с одного компакта debian-40r0-i386-xfce-CD-1.iso
[...]
>а какой пакет поставить?Что-нибудь вроде man-pages и man-pages-ru
Поищите с помощью apt-cache search man-page
>у меня таких man'ов нет...
У меня, в ALT Linux, в пакетах man-pages, man-pages-ru и man-pages-POSIX
>[...]
>>а какой пакет поставить?
>
>Что-нибудь вроде man-pages и man-pages-ru
>
>Поищите с помощью apt-cache search man-page
>
>>у меня таких man'ов нет...
>
>У меня, в ALT Linux, в пакетах man-pages, man-pages-ru и man-pages-POSIXнашел, спасибо
apt-get install manpages-dev
>>>error.h тут лишний.
>>
>>Наверное, имелось ввиду errno.h.
>
>А в чем разница?Откройте /usr/include/error.h и посмотрите -- ничего полезного (сейчас) там для вас нет :)
А в man errno написано, что она в errno.h
>У Б. Моли в "Unix/Linux. Теория и практика программирования."
> perror() применяеться ваапсче без подключения ни errno.h ни error.h )
> у меня компилер ругаеться если я их не включаю и использую
>что то из этих фалов, хотя собирает и работает )Наверное это сделано для краткости примеров (в книге исходники печатать...)
А вот в настоящих программах компилятор ругаться не должен, нужно писать так "чисто и аккуратно", как только можно. Поэтому читаем man perror и согласно нему включаем stdio.h (да, у вас он уже есть)