Обмен данными между родительским процессом и дочерним(fork)

sprit

Новичок
Обмен данными между родительским процессом и дочерним(fork)

Есть следующий скрипт
PHP:
<?
//Получение списка ссылок $DestinationList
define(MAXPROCESS,25);
for ($ichildren=0;$ichildren<=MAXPROCESS;$ichildren++){
   $MyDestinationList = array_slice($DestinationList,$ichildren*$CountChildrenDest,$CountChildrenDest,true);
   $pid = pcntl_fork();
   if ($pid == -1) {
	die("could not fork");
   } elseif ($pid) {
       //"I'm the Parent\n";
       $ThreadsCount++;
   } else {
	foreach($DestinationList as $DestName => $CurVal){
		// Выполнение запросов к различным серверам
	};
	// !!! Здесь нужно передать все данные родительскому процессу(Как лучше реализовать)
        exit;
   }
}
// Ожидание завершения всех дочерних процессов
while ($ThreadsCount>0){
      pcntl_wait($status);
	  $ThreadsCount--;
}
// Вывод результатов работы дочерних процессов
?>
необходимо все данные после отработки дочернего скрипта передать родительскому.
Как лучше это реализовать?
При использовании общей памяти обязательно симафор ставить?
 

CCCP_MOCKBA

Новичок
Я это делаю через БД.
Можно через файл, только ставить ему блокировку. Потомок записал, поставил блокировку, родитель прочел, блокировку снял и т.д.
 

sprit

Новичок
Автор оригинала: Necromant
1. Есть по крайней мере 3 способа:
1. файл
2. memcashed
3. shm
Пока попытаюсь реализовать через файл.
Единственное хотелось бы узнать, как по производительности, что быстрее будет работать?
2. А если , 2 процесса закончатся одновременно и оба начнут одновременно писать в shm ???
Если одновременно начнут писать в sharememory будет очень плохо ;)
Спасибо за ссылки, в особенности вторую.

-~{}~ 17.04.06 15:07:

Автор оригинала: CCCP_MOCKBA
Я это делаю через БД.
Через БД очень медленно, и все другие скрипты заторможу.
Можно через файл, только ставить ему блокировку. Потомок записал, поставил блокировку, родитель прочел, блокировку снял и т.д.
Тогда отпадает смысл распаралеливания, если все нити будут ждать пока родитель прочитает.

-~{}~ 17.04.06 15:36:

Встал новый вопрос, а если открываешь файл в родительском процессе, то получается он будет доступен всем дочерним процессам?
Тогда открыть необходимо один раз, а потом проверять на блокировку только?

-~{}~ 17.04.06 15:52:

Еще один вопрос, а если за место обычного fopen использовать tmpfile().
Файл удалиться после того как завершится дочерний процесс или будет дальше жить, пока не останется ни одного дискриптора этого файла?
Да и как узнать что за файл создала функция tmpfile().
 

Necromant

Новичок
Тогда отпадает смысл распаралеливания, если все нити будут ждать пока родитель прочитает.
А ты думашь родитель будет вечно читать ????

Еще один вопрос, а если за место обычного fopen использовать tmpfile().
А толку ??? Как родитель будет знать где данные ???
 

whirlwind

TDD infected, paranoid
>Встал новый вопрос, а если открываешь файл в родительском процессе, то получается он будет доступен всем дочерним процессам?

Вызов fork приводит к дублированию всех данных, в т.ч. и файловых дескрипторов. Это значит, что если в майнтреде был открыт $fh, то после выполнения fork потомок получает открытый $fh. Однако если сначала сделать fork потом открыть $fh, то с какой стати $fh будет доступен потомку? Не будет он доступен, т.к. на этот момент адресные пространства процессов абсолютно независимы.
 

sprit

Новичок
Автор оригинала: Necromant
А ты думашь родитель будет вечно читать ????
Не вечно, но данных много, так что скорее всего остальные нити будут притормаживаться.

А толку ??? Как родитель будет знать где данные ???
Если выполнить tmpfile() в родителе, то дискриптор отстанется в дочернем, т.е. уже будет указатель на файл
(см. предыдущий коментарий)

-~{}~ 17.04.06 17:02:

Пока реализовал, так
PHP:
<? 
//Получение списка ссылок $DestinationList 
define(MAXPROCESS,25); 
$ShareFileHandler = tmpfile();
for ($ichildren=0;$ichildren<=MAXPROCESS;$ichildren++){ 
   $MyDestinationList = array_slice($DestinationList,$ichildren*$CountChildrenDest,$CountChildrenDest,true); 
   $pid = pcntl_fork(); 
   if ($pid == -1) { 
    die("could not fork"); 
   } elseif ($pid) { 
       //"I'm the Parent\n"; 
       $ThreadsCount++; 
   } else { 
    foreach($DestinationList as $DestName => $CurVal){ 
        // Выполнение запросов к различным серверам 
    }; 
    // !!! Здесь нужно передать все данные родительскому процессу(Как лучше реализовать) 
		$tryCount = 0;
		while (($tryCount<6000) && (!flock($ShareFileHandler,LOCK_EX))){
					$tryCount++;
					sleep(1);
				};
			$ByteWritten = fwrite($ShareFileHandler, $FileBuffreOut);
		flock($ShareFileHandler, LOCK_UN);
		echo "Process $ichildren Fineshed.$ByteWritten bytes has been written after $tryCount try\n";
		fclose($ShareFileHandler);
        	exit;
   } 
} 
// Ожидание завершения всех дочерних процессов 
while ($ThreadsCount>0){ 
      pcntl_wait($status); 
      $ThreadsCount--; 
} 
// Вывод результатов работы дочерних процессов 
fseek($ShareFileHandler, 0);
$QueryValues = '';
while (strlen($buffer = fread($ShareFileHandler, 1024))>0){
	$QueryValues.=$buffer;
};
fclose($ShareFileHandler);
?>
Тестирвоание прошел успешно, запустил в работу, посмотрю что получится
 
Сверху