Как я могу поставить указатель на трубу? - PullRequest
2 голосов
/ 09 июня 2009

Скажем, у меня есть указатель на некоторую структуру в потоке, и я хочу передать его родительскому процессу через канал.


Пример:

MyType * someType; 

Затем я хочу привести someType к void * и положить его на трубу. Как это можно сделать?

Ответы [ 4 ]

13 голосов
/ 09 июня 2009

Хотя вы можете физически передавать указатель на родительский процесс, значение будет для этого процесса бессмысленным, и в вашем лучшем случае будет немедленный сбой. Указатели указывают адрес объекта в памяти. Этот адрес будет действителен только в контексте дочернего процесса и будет указывать на совершенно другой объект в родительском процессе.

Вам нужно будет выполнить одно из следующих действий, чтобы включить этот сценарий

  • Передайте весь объект через канал в некотором сериализованном из
  • Передайте указатель относительно базы разделяемой памяти между процессами и выполните соответствующее исправление в родительском процессе.

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

Обратите внимание, мой ответ был написан, когда был задан вопрос о том, как передать указатель между дочерним и родительским процессами. Позже он был обновлен до темы.

4 голосов
/ 09 июня 2009

Другой вариант - сохранить объект в общей памяти, а затем передать идентификатор сегмента родительскому процессу.

Затем родитель может прикрепить к памяти и получить доступ / изменить объект.

Это дает некоторую предысторию: http://fscked.org/writings/SHM/shm.html

2 голосов
/ 10 июня 2009

Читая между строками в этом и другом вопросе, который вы цитируете, вы используете «родительский процесс» для ссылки на поток основного процесса и «поток» для ссылки на новый поток, созданный в этом же процессе. Это вызывает путаницу как в отношении вашей проблемы, так и в отношении других, пытающихся ответить на вопросы.

В этом сценарии существует ровно один процесс с двумя потоками. Первый поток был создан для вас, когда ОС запустила процесс. Второй был создан намеренно первым. Вы решили использовать каналы для связи между этими потоками.

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

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

Имея все это в виду, вам просто нужно договориться с самим собой о представлении указателя. Самый простой ответ - просто записать sizeof(void *) байт в канал. При считывании вы помещаете эти байты обратно в переменную-указатель и возвращаете их в реальный тип. Конечно, ваш окружающий протокол должен знать, что это за тип.

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

1 голос
/ 10 июня 2009

Поместите его в разделяемую память и передайте указатель относительно базы разделяемой памяти. Приведение указателей зависит от того, как ваш компилятор выравнивает объекты. Помните, что при получении относительных позиций указателя, арифметика указателя основана на размере указанной вещи.

...