Подтвердить что ты не робот

Возможно обмен данными в памяти между двумя отдельными процессами?

У меня есть сервер xmlrpc с использованием Twisted. На сервере хранится огромное количество данных, хранящихся в памяти. Возможно ли иметь второй, отдельный сервер xmlrpc, который может получить доступ к объекту в памяти на первом сервере?

Итак, serverA запускается и создает объект. serverB запускается и может считывать с объекта в serverA.

* РЕДАКТИРОВАТЬ *

Данные для совместного использования - это список из 1 миллиона кортежей.

4b9b3361

Ответ 1

Без глубокой и темной перезаписи основного времени выполнения Python (чтобы обеспечить форсирование распределителя, который использует данный сегмент разделяемой памяти и обеспечивает совместимые адреса между разрозненными процессами), нет возможности "обмениваться объектами в памяти" в любом общий смысл. Этот список будет содержать миллион адресов кортежей, каждый кортеж состоит из адресов всех его элементов, и каждый из этих адресов будет назначен pymalloc таким образом, который неизбежно будет варьироваться между процессами и распространяется по всей куче.

В любой системе, кроме Windows, можно создать подпроцесс, который имеет доступ только для чтения к объектам в родительском пространстве процесса... пока родительский процесс не изменит эти объекты. Это получилось при вызове os.fork(), что на практике "моментальные снимки" все пространство памяти текущего процесса и запускает другой одновременный процесс копирования/моментального снимка. Во всех современных операционных системах это очень быстро благодаря подходу "копирование на запись": страницы виртуальной памяти, которые не изменяются ни одним из процессов после того, как вилка на самом деле не скопирована (доступ к тем же страницам не используется совместно); как только любой процесс изменяет любой бит на ранее разделяемой странице, poof, эта страница будет скопирована, а таблица страниц изменена, поэтому процесс модификации теперь имеет свою собственную копию, в то время как другой процесс все еще видит исходный.

Эта чрезвычайно ограниченная форма совместного использования в некоторых случаях может оставаться спасателем (хотя она крайне ограничена: помните, например, что добавление ссылки на общий объект считается как "изменение" этого объекта из-за количества ссылок, и так будет принудительно копировать страницу!)... кроме Windows, конечно, где он недоступен. С помощью этого единственного исключения (которое, как я думаю, не будет охватывать ваш случай использования) разделение графиков объектов, которое включает ссылки/указатели на другие объекты, в основном неосуществимо - и почти любые объекты, представляющие интерес для современных языков (включая Python) подпадает под эту классификацию.

В экстремальных (но достаточно простых) случаях можно получить совместное использование, отказавшись от представления собственной памяти таких графов объектов. Например, список из миллиона кортежей, каждый с шестнадцатью поплавками, может фактически быть представлен как единый блок с общей памятью 128 МБ - все 16M-поплавки в представлении IEEE с двойной точностью, заложенные до конца - с небольшой фиксацией сверху, чтобы "сделать это похожим", вы обращаетесь к вещам обычным способом (и, конечно же, не слишком мало-после-все-прокладки должны также заботиться о чрезвычайно волосатых проблемах синхронизации между процессами, которые обязательно возникнут;-). Это только становится более увядающим и более сложным оттуда.

Современные подходы к concurrency все более и более презирают подход "ничего общего" в пользу "ничего общего", когда задачи обмениваются сообщениями (даже в многоядерных системах с использованием потоков и общих адресных пространств, проблем синхронизации и производительность достигает HW с точки зрения кеширования, конвейера и т.д., когда большие области памяти активно модифицируются несколькими ядрами одновременно, отталкивают людей).

Например, модуль многопроцессорности в стандартной библиотеке Python в основном опирается на травление и отправку объектов туда и обратно, а не на совместное использование памяти (конечно, не в R/W-режиме!).

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

Ответ 2

mmap.mmap(0, 65536, 'GlobalSharedMemory')

Я думаю, что тег ( "GlobalSharedMemory" ) должен быть одинаковым для всех процессов, желающих разделить одну и ту же память.

http://docs.python.org/library/mmap.html

Ответ 3

В Python имеется пара 1 сторонних библиотек, доступных для манипуляций с общей памятью низкого уровня:

  • sysv_ipc
    • > Для систем, несовместимых с posix
  • posix_ipc
    • > Работает в Windows с cygwin

Оба из них доступны через pip

[1] Другой пакет, shm, доступен, но устарел. См. эту страницу для сравнения библиотек.

Пример кода для обмена сообщениями C на Python c/o Martin O ' Хэнлон:

shmwriter.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, const char **argv)
{
   int shmid;
   // give your shared memory an id, anything will do
   key_t key = 123456;
   char *shared_memory;

   // Setup shared memory, 11 is the size
   if ((shmid = shmget(key, 11, IPC_CREAT | 0666)) < 0)
   {
      printf("Error getting shared memory id");
      exit(1);
   }
   // Attached shared memory
   if ((shared_memory = shmat(shmid, NULL, 0)) == (char *) -1)
   {
      printf("Error attaching shared memory id");
      exit(1);
   }
   // copy "hello world" to shared memory
   memcpy(shared_memory, "Hello World", sizeof("Hello World"));
   // sleep so there is enough time to run the reader!
   sleep(10);
   // Detach and remove shared memory
   shmdt(shmid);
   shmctl(shmid, IPC_RMID, NULL);
}

shmreader.py

import sysv_ipc

# Create shared memory object
memory = sysv_ipc.SharedMemory(123456)

# Read value from shared memory
memory_value = memory.read()

# Find the 'end' of the string and strip
i = memory_value.find('\0')
if i != -1:
    memory_value = memory_value[:i]

print memory_value

Ответ 4

Вы можете написать библиотеку C для создания и управления массивами разделяемой памяти для вашей конкретной цели, а затем использовать ctypes для доступа к ним с Python.

Или, поместите их в файловую систему в /dev/shm (это tmpfs). Вы бы сэкономили много усилий на разработку для очень небольших издержек производительности: чтение/запись из файловой системы tmpfs - это немного больше, чем memcpy.

Ответ 6

Почему бы не вставить общие данные на сервер memcache? то оба сервера могут получить к нему доступ довольно легко.

Ответ 7

Простой на самом деле. Вы можете просто использовать общую память. В этом примере создается список кортежей (python) на С++ и делится им с процессом python, который затем может использовать список кортежей. Чтобы использовать между двумя процессами Python, просто сделайте свой доступ как ACCESS_WRITE в процессе отправителя и вызовите метод write.

С++ (процесс отправителя):

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#include <string>

#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("[(1, 2, 3), ('a', 'b', 'c', 'd', 'e'), (True, False), 'qwerty']");

int _tmain(int argc, _TCHAR* argv[])
{
     HANDLE hMapFile;
   LPCTSTR pBuf;

   hMapFile = CreateFileMapping(
                 INVALID_HANDLE_VALUE,    // use paging file
                 NULL,                    // default security
                 PAGE_READWRITE,          // read/write access
                 0,                       // maximum object size (high-order DWORD)
                 BUF_SIZE,                // maximum object size (low-order DWORD)
                 szName);                 // name of mapping object

   if (hMapFile == NULL)
   {
      _tprintf(TEXT("Could not create file mapping object (%d).\n"),
             GetLastError());
      return 1;
   }
   pBuf = (LPTSTR) MapViewOfFile(hMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,
                        0,
                        BUF_SIZE);

   if (pBuf == NULL)
   {
      _tprintf(TEXT("Could not map view of file (%d).\n"),
             GetLastError());

       CloseHandle(hMapFile);
       return 1;
   }

   CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    _getch();

   UnmapViewOfFile(pBuf);

   CloseHandle(hMapFile);
    return 0;
}

Python (процесс приемника):

import mmap
shmem = mmap.mmap(0,256,"Global\\MyFileMappingObject",mmap.ACCESS_READ)
msg_bytes = shmem.read()
msg_utf16 = msg_bytes.decode("utf-16")
code = msg_utf16.rstrip('\0')
yourTuple = eval(code)

Ответ 8

Почему бы просто не использовать базу данных для общих данных? У вас есть множество облегченных вариантов, в которых вам не нужно беспокоиться о проблемах concurrency: sqlite, любом из классов баз данных nosql/key-value и т.д.