Как вернуть фрагменты cJSON по родительскому процессу, используя POSIX? - PullRequest
0 голосов
/ 29 января 2019

tl; dr: Как мне настроить cJSON для выделения памяти в дочерних процессах, чтобы родитель мог видеть результирующие структуры?


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

Поскольку сводные данные являются дорогостоящими в вычислительном отношении (пользователь запрашивает выполнение определенных вычислений как часть сводок), я бынапример, fork(2) для каждого запрошенного продукта, затем его выборка, обработка и суммирование в cJSON_Object (технически cJSON*, но "конструктор" - cJSON_CreateObject)и затем заставляет родительский поток ждать, пока все дочерние элементы не вернут свои cJSON_Object объекты, чтобы объединиться, выполнить некоторую постобработку, а затем, наконец, маршалировать в строку для возврата.Из-за постобработки я хотел бы вернуть родительскому элементу cJSON_Object вместо того, чтобы дочерние потоки возвращали строки.

Теперь я вижу cJSON.h:144 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks), который принимаетcJSON.h:125 struct internal_hooks, который позволяет вам задавать пользовательские реализации malloc() и free() ... что было бы замечательно, если бы я мог найти версии, которые выделяют общую память ... и разделяют тот же тип.Самым близким, что я нашел, был shmalloc / shfree, но это из библиотеки OpenMPI , и это выглядит просто излишним для того, что должно быть простыми рабочими потоками ...

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

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

PS - Желательно, чтобы решение былоограничимся API POSIX, но приемлем только Linux и дополнительные библиотеки в качестве крайней меры.

Ответы [ 2 ]

0 голосов
/ 29 января 2019

К сожалению, это не так просто, как выделить какой-либо объект в сегменте разделяемой памяти.cJSON объект - это связанная структура данных, что неудивительно, если учесть, что объекты JSON могут состоять из вложенных списков и хэшей.

typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *prev;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;
    ...
}

Эта структура указателей и указателей хранения в области разделяемой памяти можетне быть хорошей идеейКаждый процесс имеет свое собственное пространство виртуальной памяти, и сегмент общей памяти может не отображаться на один и тот же адрес в обоих процессах.В этом случае одно и то же значение указателя будет указывать на действительный объект в одном адресном пространстве, но в другом адресном пространстве оно может указывать на мусор.

0 голосов
/ 29 января 2019

Я не проверял это, и это кажется хакерским, но это лучшее, о чем я думал до сих пор:

Я нашел shmget(3).Сигнатура типа не совместима, поэтому я подумал, что смогу ее обернуть.В каждом дочернем элементе я мог генерировать уникальное целое число для использования в качестве key_t и выделять достаточно памяти, чтобы вместить ответ.Затем предоставьте мой собственный malloc(), который просто выделяется из блока, выделенного shmget.Наконец, верните key_t родителю через вызов exit(3).Родительский поток получит значение key_t из wait(3), а затем сможет извлечь cJSON_Object и объединить его с другими фрагментами.

Таким образом, ответом было бы иметь начальный дочерний элемент: shmget некоторую память, а затем написать malloc() -совместимую функцию my_malloc(), которая выделяет эту shmget редактируемую память, и иметьуказатель на my_malloc(), переданный на cJSON_InitHooks через struct internal_hooks.

...