Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Паралелльные процессы в PHP
Форумы портала PHP.SU » PHP » Программирование на PHP » Паралелльные процессы в PHP

Страниц (1): [1]
 

1. SergeantPEPPER - 01 Апреля, 2008 - 09:54:44 - перейти к сообщению
Здравствуйте,
скажите а как можно распараллелить один процесс в PHP и создать, ну скажем, пять потомков этого процесса?

Или даже не порождать несколько процессов, а содавать 5 потоков одного процесса...
Не знаю даже как это нормальнее будет выглядеть?

Если не сложно, подкиньте еще ссылку на хорошую литературу. Спасибо.

Попробовал разобраться сам:

CODE (text):
скопировать код в буфер обмена
  1. <?php
  2.  
  3. $child_num = 4;
  4.  
  5.  
  6. $fpid = pcntl_fork ();
  7. if ($fpid == -1) {
  8.         die ("could not fork!\n");
  9. } elseif ($fpid) {
  10.         // father process
  11.         exit ();
  12. } else {
  13.         // mother process
  14.         for ($i = 1; $i <= $child_num; $i++)
  15.         {
  16.                 $pid = pcntl_fork ();
  17.                 if ($pid == -1) die ("Could not fork!\n");
  18.                 elseif ($pid) $pid_array[$i] = $pid;
  19.                 else {
  20.                         echo "Im child process!\n";    
  21.                 }
  22.         }      
  23. }
  24. ?>


Однако такой код почему-то каждый раз выдает разное количество фраз
Im child process ???
Не пойму почему?

P.S. Я тестирую на Unix-системе
2. SergeantPEPPER - 02 Апреля, 2008 - 09:04:49 - перейти к сообщению
Товарищи, не бросайте меня )))

Тот код, что я приводил выше был взят с какого-то сайта и был неоправданно отягащен...

Как параллелить процесс я понял, однако вот проблема в другом: каждый порожденный процесс у меня работает с базой данных MySQL, и казалось бы первый отработавший процесс должен завершить соединение с ней, отрубив от MySQL оставшиеся, НО!!!
Не знаю почему из пяти параллельных дочерних процессов соединение может отрубиться после двух, трех или четырех процессов??? Не понял - Т.е. соединение с MySQL разрывается НЕ после первого процесса и "поработать" с ней успевает каждый новый раз разное количество процессов.

Я ничего не понимаю! Объясните, пожалуйста в чем дело!
3. SergeantPEPPER - 03 Апреля, 2008 - 08:16:08 - перейти к сообщению
Ну, пообщаюсь немного сам с собой...

О причине такого странного поведения я догадался:

Так как соединение с MySQL рвется только ПОСЛЕ окончания работы с ним первого (самого быстрого) процесса, то можно предположить, что в промежутке между началом работы с MySQL и окончанием этого процесса , успевают воспользоваться текущим соединением и несколько других параллельных процессов. Ну и логично тогда, что каждый новый раз это число будет случайным... (ну или псевдослучайным)

Жаль, но проблема все же остается. Соединение с MySQL рвется и я с этим ничего поделать не могу, блин, я облазил кучу форумов и FAQ-ов, но ответа нигде нет...
А постояннам соединением через mysql_pconnect пользоваться не хочется (да в общем-то и не помогло)

Если кто-нибудь сталкивался с этим, НАПИШИТЕ please Однако
4. EuGen - 03 Апреля, 2008 - 10:34:44 - перейти к сообщению
А в чем задача, не ясно. Вам нужно, чтобы при наличии установленного соединения с БД в одном из процессов, другие процессы не могли соединиться с БД, или как?..
5. SergeantPEPPER - 04 Апреля, 2008 - 07:58:05 - перейти к сообщению
Ну для начала, я хотел бы сделать такую программу:

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

При этом: соединение с MySQL открывается в начале главного процесса. Первый (самый быстрый) дочерний процесс после общения c MySQL это соединение завершает и MySQL становится недоступным для остальных. Так вот, моя задача в том, чтобы после отработки первого процесса соединение не завершалось (т.е. сохранялось), а закрывалось в конце гланого процесса.
6. EuGen - 04 Апреля, 2008 - 09:43:19 - перейти к сообщению
То есть Вы хотите, чтобы все потомки родительского процесса работали с одним соединением с БД?
7. SergeantPEPPER - 04 Апреля, 2008 - 12:20:38 - перейти к сообщению
Да, именно так.
8. EuGen - 04 Апреля, 2008 - 13:21:39 - перейти к сообщению
Приведите, пожалуйста, кусок кода, где Вы работаете с соединением с БД (то есть как Вы обрабатываете его) и как Вы распараллеливаете процесс (я так понял, что Вы это делаете уже не так, как приведен Ваш пример выше).
9. expired - 04 Апреля, 2008 - 19:01:43 - перейти к сообщению
хм, странно я видел люди пытались сделать что то подобное для кроны,
и для интернет чата,

а для чего вам это нужно?
10. SergeantPEPPER - 05 Апреля, 2008 - 15:48:02 - перейти к сообщению
Извиняюсь за длительную задержку. Хм

Вот код (здесь все дочерние процессы работают через функцию child_main):

CODE (text):
скопировать код в буфер обмена
  1. // функция для дочернего потока
  2. function child_main ()
  3. {
  4.         $cpid = getmypid ();
  5.         //echo "Child process take off: $cpid\n";
  6.         DoQuery ("INSERT INTO `sends` (`login`, `email`, `message`) VALUES ('login-$cpid', 'email-$cpid', 'message-$cpid')")
  7.                 OR die ('MySQL error: ' . mysql_error () . "\n");
  8.         sleep (2);
  9. }
  10.  
  11. DoQuery("SET wait_timeout=28800");
  12.  
  13. for ($i = 1; $i <= 5; $i++)
  14. {
  15.         $pid = pcntl_fork ();
  16.         if ($pid == -1) die ("Error: pcntl_fork ()!\n");
  17.         elseif ($pid == 0) exit (child_main ());
  18.         else {
  19.                 $all_childs[i] = $pid;
  20.         }
  21. }
  22.  
  23. for ($i = 1; $i <= 5; $i++)
  24. {
  25.         $pid = $all_pids[i];
  26.         // берем статус дочернего процесса
  27.         // в $status передалась информация статуса процесса (при выходе)
  28.         $pid = pcntl_wait ($status);
  29.  
  30.         // есть ли статус успешного выхода
  31.         if (pcntl_wifexited ($status))
  32.         {
  33.                 $code = pcntl_wexitstatus ($status);
  34.                 echo "Process $pid return exit code: $code\n";
  35.         } else {
  36.                 echo "Process $pid was force destroyed\n";
  37.         }
  38. }


А понадобилось мне это, чтобы решить проблему, которая уже отпала... Улыбка
НО ради интереса и опыта хочу все-таки найти решение данного вопроса.

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

 

Powered by ExBB FM 1.0 RC1