URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 6665
[ Назад ]

Исходное сообщение
"Процесный движок"

Отправлено tigo , 09-Авг-07 16:11 
Всем доброго времени суток!

Короче это я пытаюсь сделать "процесный движок", софтина должна рождать потомков в количесве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;
                }
        }

}

Работает ли это так как мне надо? Если нет, то почему? И как отлаживать такие приложения?


Содержание

Сообщения в этом обсуждении
"Процесный движок"
Отправлено anonymous , 09-Авг-07 16:49 
>Работает ли это так как мне надо? Если нет, то почему? И
>как отлаживать такие приложения?

Дочерние процессы не выходят, а снова попадают в while(1) и ведут себя сами как родители.  Поздравляю, fork-бомба готова!


"Процесный движок"
Отправлено tigo , 09-Авг-07 16:53 
>>Работает ли это так как мне надо? Если нет, то почему? И
>>как отлаживать такие приложения?
>
>Дочерние процессы не выходят, а снова попадают в while(1) и ведут себя
>сами как родители.  Поздравляю, fork-бомба готова!

Ну не совсем так...
там проверочка на чилда, если чилд то каунтер процесов обнуляеться...
читай пожалуйста внимательно


"Процесный движок"
Отправлено anonymous , 09-Авг-07 17:22 
>Ну не совсем так...
> там проверочка на чилда, если чилд то каунтер процесов обнуляеться...
> читай пожалуйста внимательно

Извиняюсь, я немного запутался.  По-моему, код работает немного неочевидно, и я бы его переписал так:

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 */
    }
  }
}


"Процесный движок"
Отправлено tigo , 09-Авг-07 17:37 
Согласен так логичнее выглядит,
только while(pid == wait(NULL)) ждет только одного потомка и потом стартует тоже только одного.
Интересно которого?



"Процесный движок"
Отправлено vic , 09-Авг-07 16:54 
>>Работает ли это так как мне надо? Если нет, то почему? И
>>как отлаживать такие приложения?
>
>Дочерние процессы не выходят, а снова попадают в while(1) и ведут себя
>сами как родители.  Поздравляю, fork-бомба готова!

нет, там условие:
if(ppid == getpid() && pc > 0) {
т.е. дети не будут форкаться


"Процесный движок"
Отправлено vic , 09-Авг-07 16:58 
>Работает ли это так как мне надо? Если нет, то почему?

Мы не телепаты и не знаем что тебе надо :)
Данный код делает несколько форков и в них спит.

> И как отлаживать такие приложения?

Тщательно и с применением всех доступных средств :)
Хотя что там отлаживать-то, он че падает или делает не то что ожидается?



"Процесный движок"
Отправлено tigo , 09-Авг-07 17:03 
>>Работает ли это так как мне надо? Если нет, то почему?
>
>Мы не телепаты и не знаем что тебе надо :)
>Данный код делает несколько форков и в них спит.
>
>> И как отлаживать такие приложения?
>
>Тщательно и с применением всех доступных средств :)
>Хотя что там отлаживать-то, он че падает или делает не то что
>ожидается?

Всегда должно быть количесвто потомков равное.
По порядку,
Рождаеться MAXPROC потомков,
допустим один засыпает на 20сек и второй 60сек и тд
Просыпаеться первый черз 20сек и заверщает работу
надо что бы родитель пускал еще одного вместо него


"Процесный движок"
Отправлено vic , 09-Авг-07 17:33 
>[оверквотинг удален]
>>Тщательно и с применением всех доступных средств :)
>>Хотя что там отлаживать-то, он че падает или делает не то что
>>ожидается?
>
>Всегда должно быть количесвто потомков равное.
>По порядку,
>Рождаеться MAXPROC потомков,
>допустим один засыпает на 20сек и второй 60сек и тд
>Просыпаеться первый черз 20сек и заверщает работу
>надо что бы родитель пускал еще одного вместо него

Проснувшись потомок идет на while(1), т.е. не завершается.


"Процесный движок"
Отправлено tigo , 09-Авг-07 17:35 
>[оверквотинг удален]
>>>ожидается?
>>
>>Всегда должно быть количесвто потомков равное.
>>По порядку,
>>Рождаеться MAXPROC потомков,
>>допустим один засыпает на 20сек и второй 60сек и тд
>>Просыпаеться первый черз 20сек и заверщает работу
>>надо что бы родитель пускал еще одного вместо него
>
>Проснувшись потомок идет на while(1), т.е. не завершается.

ага уже понял )


"Процесный движок"
Отправлено vic , 09-Авг-07 17:39 
>[оверквотинг удален]
>>>ожидается?
>>
>>Всегда должно быть количесвто потомков равное.
>>По порядку,
>>Рождаеться MAXPROC потомков,
>>допустим один засыпает на 20сек и второй 60сек и тд
>>Просыпаеться первый черз 20сек и заверщает работу
>>надо что бы родитель пускал еще одного вместо него
>
>Проснувшись потомок идет на while(1), т.е. не завершается.

И сразу же вопрос, зачем породив N процессов делать завершение и новый форк для них? Не лучше ли если процесс выполнив задачу просто снова засыпает?


"Процесный движок"
Отправлено tigo , 09-Авг-07 17:44 
>[оверквотинг удален]
>>>Рождаеться MAXPROC потомков,
>>>допустим один засыпает на 20сек и второй 60сек и тд
>>>Просыпаеться первый черз 20сек и заверщает работу
>>>надо что бы родитель пускал еще одного вместо него
>>
>>Проснувшись потомок идет на while(1), т.е. не завершается.
>
>И сразу же вопрос, зачем породив N процессов делать завершение и новый
>форк для них? Не лучше ли если процесс выполнив задачу просто
>снова засыпает?

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


"Процесный движок"
Отправлено Ray Dudu , 13-Авг-07 19:21 
>>[оверквотинг удален]
>Задумка такая ) некя чилд функция получает в качестве параметра элемент структуры,
>производит с ней операции и завершае работу, след аналогично. Что бы
>обработка элементов не повторялась, нечто похожее на такой способ синхронзации. Може
>есть другие варианты.. я не давно занимаюсь программированием.

вопрос 1: нужны ли тебе тут вообще процессы, может проще взять потоки? Для ОС легче их создавать. вопрос 2: зачем тебе каждый раз перезапускать процесс,может ему проще получать данные используя какойнить shared memory or pipes?
поразмысль над этим


"Процесный движок"
Отправлено elvenic , 09-Авг-07 18:36 
> И как отлаживать такие приложения?

А отлаживать - syslog()'ом (man 3 syslog). И печатать timestamps с точностью до микросекунды. (Чем и я сам сейчас, кстати, и занимаюсь :) )

Have fun!

    elvenic.



"Процесный движок"
Отправлено tigo , 09-Авг-07 19:32 
В итоге поучилось нечто такое, если где то есть ошибка сообщите. Всем спасибо за участие.

#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;
                }
        }

}


"Процесный движок"
Отправлено anonymous , 10-Авг-07 02:15 
>В итоге поучилось нечто такое, если где то есть ошибка сообщите. Всем
>спасибо за участие.

Извиняюсь за наглость в этом посте, я просто написал всё что я думаю об этом коде, я не хочу вас обидеть ни в коей мере.

Я уже показал как обычно делаются такие вещи в предыдущем посте.  А именно:

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() в отдельную строку и сделайте проверку ошибок.  логически (с первого взгляда) эта строка кода выводит текст, а реально -- ждёт потомка и только потом выводит текст. (фактически, изменяется способ исполнения программы -- она засыпает, нужно это подчеркнуть)


"Процесный движок"
Отправлено jd , 10-Авг-07 06:19 
Я бы всё-таки написал:

switch(pid = fork())
{ case -1: /* ошибка */
    ...
    break;
  case 0: /* дочерний процесс */
    ...
    exit(...);
  default: /* родитель */
    ...
    break;
}

И у вас тут опечатка: "if(pid == fork())"


"Процесный движок"
Отправлено tigo , 10-Авг-07 09:33 
>[оверквотинг удален]
>см. выше насчёт идиомы программирования
>
>switch из 0 и default это эффективно является тем же if() что
>и в идиоме, только это снова неочевидно
>
>printf("Запущенно потомков - %d\n Ждем окончание работы потомка PID=%d\n", child_proc_count, wait(&status));
>вынесите wait() в отдельную строку и сделайте проверку ошибок.  логически (с
>первого взгляда) эта строка кода выводит текст, а реально -- ждёт
>потомка и только потом выводит текст. (фактически, изменяется способ исполнения программы
>-- она засыпает, нужно это подчеркнуть)

Действительн, огромное спасибо за полезные комментарии, я не очень давно программирую на Си :-) и с удовольствием приму Ваши комментарии к сведению, и поступлю в соответсвии с ними. У самого голова пухнет от чтения чужих кодов... В любом случае это еще не оконченный продукт и в данном виде, так сказать, существует только на бумаге и ввиде учебного примера(для меня же :-). А в общем, очень рад на такую реакцию знаменитого сообщества ) Большое вам спасибо, Вашими стараниями и из меня получиться хороший программист!

PS Так настроение поднял сутра )


"Процесный движок"
Отправлено phpcoder , 10-Авг-07 09:12 
[...]
>#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>


"Процесный движок"
Отправлено anonymous , 10-Авг-07 12:35 
>error.h тут лишний.

Наверное, имелось ввиду errno.h.


"Процесный движок"
Отправлено phpcoder , 10-Авг-07 12:39 
>>error.h тут лишний.
>
>Наверное, имелось ввиду errno.h.

Даже если и так -- errno.h был бы тоже лишним :)


"Процесный движок"
Отправлено tigo , 10-Авг-07 12:46 
>>error.h тут лишний.
>
>Наверное, имелось ввиду errno.h.

А в чем разница?

У Б. Моли в "Unix/Linux. Теория и практика программирования."
perror() применяеться ваапсче без подключения ни errno.h ни error.h )
у меня компилер ругаеться если я их не включаю и использую что то из этих фалов, хотя собирает и работает )


"Процесный движок"
Отправлено phpcoder , 10-Авг-07 12:49 
>>>error.h тут лишний.
>>
>>Наверное, имелось ввиду errno.h.
>
>А в чем разница?

man 3 errno
man 3 error

>У Б. Моли в "Unix/Linux. Теория и практика программирования."
> perror() применяеться ваапсче без подключения ни errno.h ни error.h )

У меня в man'е написано, что perror() находится в stdio.h



"Процесный движок"
Отправлено tigo , 10-Авг-07 13:04 
>[оверквотинг удален]
>>
>>А в чем разница?
>
>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


"Процесный движок"
Отправлено phpcoder , 10-Авг-07 13:18 
[...]
>а какой пакет поставить?

Что-нибудь вроде man-pages и man-pages-ru

Поищите с помощью apt-cache search man-page

>у меня таких man'ов нет...

У меня, в ALT Linux, в пакетах man-pages, man-pages-ru и man-pages-POSIX


"Процесный движок"
Отправлено tigo , 10-Авг-07 13:27 
>[...]
>>а какой пакет поставить?
>
>Что-нибудь вроде 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


"Процесный движок"
Отправлено anonymous , 10-Авг-07 12:57 
>>>error.h тут лишний.
>>
>>Наверное, имелось ввиду errno.h.
>
>А в чем разница?

Откройте /usr/include/error.h и посмотрите -- ничего полезного (сейчас) там для вас нет :)

А в man errno написано, что она в errno.h

>У Б. Моли в "Unix/Linux. Теория и практика программирования."
> perror() применяеться ваапсче без подключения ни errno.h ни error.h )
> у меня компилер ругаеться если я их не включаю и использую
>что то из этих фалов, хотя собирает и работает )

Наверное это сделано для краткости примеров (в книге исходники печатать...)

А вот в настоящих программах компилятор ругаться не должен, нужно писать так "чисто и аккуратно", как только можно.  Поэтому читаем man perror и согласно нему включаем stdio.h (да, у вас он уже есть)