Обзор методов обмена данными между процессами
Папка "tmp" часто используется для обмена данными между процессами на компьютере или сервере. Этот подход особенно полезен, если ваше приложение состоит из нескольких независимых процессов или модулей, которые должны обмениваться информацией.
Запись данных в файлы
Один процесс может записывать данные в файлы в папке "tmp", а другие процессы могут читать эти файлы для получения информации. Например, процесс-производитель может создавать временные файлы с результатами вычислений, а процесс-потребитель может читать эти файлы для дальнейшей обработки.
Пример на PHP:
// Процесс-производитель (producer.php)
$data = ['result' => 'обработанные данные', 'timestamp' => time()];
$tmp_file = sys_get_temp_dir() . '/process_data_' . getmypid() . '.tmp';
file_put_contents($tmp_file, json_encode($data));
chmod($tmp_file, 0666); // Разрешаем чтение другим процессам
// Процесс-потребитель (consumer.php)
$pattern = sys_get_temp_dir() . '/process_data_*.tmp';
foreach (glob($pattern) as $tmp_file) {
if (file_exists($tmp_file)) {
$data = json_decode(file_get_contents($tmp_file), true);
// Обработка данных
echo "Получены данные: " . $data['result'] . "\n";
// Удаляем обработанный файл
unlink($tmp_file);
}
}
Использование именованных каналов
Именованные каналы (FIFO) представляют собой специальные файлы, которые можно использовать для однонаправленной передачи данных между процессами. Один процесс может записывать данные в именованный канал, а другой процесс может читать эти данные из того же канала.
Создание и использование именованных каналов:
// Создание именованного канала (FIFO)
$fifo_path = sys_get_temp_dir() . '/my_pipe.fifo';
// Создаем FIFO если не существует
if (!file_exists($fifo_path)) {
posix_mkfifo($fifo_path, 0666);
}
// Процесс-писатель
$fifo = fopen($fifo_path, 'w');
fwrite($fifo, "Данные для передачи\n");
fclose($fifo);
// Процесс-читатель
$fifo = fopen($fifo_path, 'r');
$data = fread($fifo, 1024);
fclose($fifo);
echo "Получены данные: $data";
Семафоры и блокировки
Семафоры и блокировки могут использоваться для синхронизации доступа к общим ресурсам, таким как файлы в папке "tmp". Например, если несколько процессов пытаются записать данные в один и тот же файл, блокировки могут использоваться для предотвращения конфликтов доступа.
Реализация файловых блокировок:
// Функция для безопасной записи с блокировкой
function safe_write($filename, $data) {
$lock_file = $filename . '.lock';
$max_wait = 30; // Максимальное время ожидания в секундах
$start_time = time();
// Ожидаем освобождения блокировки
while (file_exists($lock_file) && (time() - $start_time) < $max_wait) {
usleep(100000); // Ждем 100ms
}
// Создаем блокировку
touch($lock_file);
try {
// Выполняем запись
file_put_contents($filename, $data, LOCK_EX);
} finally {
// Освобождаем блокировку
unlink($lock_file);
}
}
// Использование
$shared_file = sys_get_temp_dir() . '/shared_data.tmp';
safe_write($shared_file, "Общие данные");
Использование семафоров в Linux:
// Создание семафора
$sem_key = ftok(__FILE__, 't');
$sem_id = sem_get($sem_key, 1, 0666, 1);
// Процесс получает семафор
if (sem_acquire($sem_id)) {
try {
// Критическая секция - работа с общими ресурсами
file_put_contents($shared_file, "Данные под защитой семафора");
} finally {
// Освобождаем семафор
sem_release($sem_id);
}
}
Передача сообщений
Папка "tmp" также может использоваться для передачи сообщений между процессами. Например, один процесс может создавать временные файлы с данными или сообщениями для других процессов, которые затем могут их прочитать и обработать.
Система очереди сообщений:
// Класс для простой очереди сообщений
class TempMessageQueue {
private $queue_dir;
public function __construct($queue_name) {
$this->queue_dir = sys_get_temp_dir() . '/' . $queue_name;
if (!is_dir($this->queue_dir)) {
mkdir($this->queue_dir, 0700, true);
}
}
public function send($message) {
$filename = $this->queue_dir . '/msg_' . microtime(true) . '_' . uniqid() . '.tmp';
file_put_contents($filename, serialize($message));
return $filename;
}
public function receive() {
$files = glob($this->queue_dir . '/msg_*.tmp');
if (empty($files)) {
return null;
}
sort($files);
$filename = $files[0];
$message = unserialize(file_get_contents($filename));
unlink($filename);
return $message;
}
}
// Использование очереди
$queue = new TempMessageQueue('my_app');
$queue->send(['type' => 'notification', 'message' => 'Привет!']);
$message = $queue->receive();
Безопасность и производительность
При использовании папки "tmp" для обмена данными между процессами важно следить за безопасностью и целостностью данных, а также учитывать производительность и надежность этого подхода.
Рекомендации по безопасности:
- Устанавливайте правильные права доступа к файлам (обычно 600 или 660)
- Валидируйте все входящие данные из временных файлов
- Используйте безопасные имена файлов для предотвращения атак
- Регулярно очищайте старые временные файлы
Советы по производительности:
- Используйте буферизацию для частых операций записи
- Избегайте блокировок на длительное время
- Используйте in-memory решения для высоконагруженных систем
- Оптимизируйте размер передаваемых данных
Практические примеры
Пример 1: Мониторинг прогресса выполнения
// Рабочий процесс
$progress_file = sys_get_temp_dir() . '/task_progress_' . getmypid() . '.tmp';
for ($i = 0; $i <= 100; $i += 10) {
// Выполняем работу
sleep(1);
// Сохраняем прогресс
file_put_contents($progress_file, $i);
}
// Мониторинг процесса
function get_progress($pid) {
$progress_file = sys_get_temp_dir() . '/task_progress_' . $pid . '.tmp';
if (file_exists($progress_file)) {
return (int)file_get_contents($progress_file);
}
return 0;
}
Пример 2: Разделение задач между процессами
// Главный процесс распределяет задачи
$tasks = range(1, 100);
$worker_count = 4;
foreach ($tasks as $task) {
$task_file = sys_get_temp_dir() . '/task_' . $task . '.tmp';
file_put_contents($task_file, serialize($task));
}
// Рабочие процессы
for ($i = 0; $i < $worker_count; $i++) {
$pid = pcntl_fork();
if ($pid == 0) {
// Дочерний процесс
while ($task_file = glob(sys_get_temp_dir() . '/task_*.tmp')[0] ?? null) {
$task = unserialize(file_get_contents($task_file));
unlink($task_file);
// Обработка задачи
process_task($task);
}
exit(0);
}
}
Полезные ресурсы для разработчиков: Документация PHP по семафорам , Руководство по FIFO в Linux , Мультипроцессинг в PHP , VPS для многопроцессорных приложений