Можно ли использовать указатели функций в процессах?

Я знаю, что каждый процесс создает свое собственное адресное пространство памяти, однако мне было интересно,

Если бы процесс A имел такую ​​функцию, как:

int DoStuff() { return 1; }

и typedef указателя, например:

typedef int(DoStuff_f*)();

и функция получения, например:

DoStuff_f * getDoStuff() { return DoStuff; }

и волшебный способ связи с процессом B через... например, boost::interprocess

можно ли передать указатель функции процессу B и вызвать

DoStuff процесса A непосредственно из процесса B?


person Maciek    schedule 13.10.2009    source источник
comment
Укажите ОС, с которой вы имеете дело. Ответ на этот вопрос сильно отличается для vxWorks и Linux.   -  person kmarsh    schedule 13.10.2009
comment
Согласен - все ответы без ответов следует понимать как не переносимые и / или не в моей ОС. На некоторых платформах с очень легковесными операционками нет защищенной памяти, и она просто будет работать.   -  person Steve Jessop    schedule 13.10.2009
comment
Я предполагаю, что это Windows. Мое предположение основано на ранних вопросах Мацика и стиле именования функций :)   -  person Kirill V. Lyadvinsky    schedule 13.10.2009
comment
@onebyone: В основном, если вы работаете в SOC без виртуального адресного пространства, это может быть потенциально возможно.   -  person Martin York    schedule 13.10.2009


Ответы (6)


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

Например, если у вас было

////PROCESS A////
int processA_myfun() { return 3; }
// get a pointer to pA_mf and pass it to process B

////PROCESS B////
int processB_myfun() { return 4; } // This happens to be at the same virtual address as pA_myfun
// get address from process A
int x = call_myfun(); // call via the pointer
x == 4;  // x is 4, because we called process B's version!

Если процессы A и B выполняют один и тот же код, вы можете получить идентичные функции по одинаковым адресам, но вы все равно будете работать со структурами данных и глобальной памятью B! Итак, короткий ответ: нет, это не то, как вы хотите это сделать!

Кроме того, меры безопасности, такие как рандомизация макета адресного пространства, могут помешать таким "трюкам" когда-либо работать. .

Вы путаете IPC и RPC. IPC предназначен для передачи данных, таких как ваши объекты или текст. RPC предназначен для выполнения кода в удаленном процессе.

person Steven Schlansker    schedule 13.10.2009

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

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

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

person Kirill V. Lyadvinsky    schedule 13.10.2009

Если бы вы попытались использовать указатель функции процесса A из процесса B, вы бы не вызывали процесс A — вы вызывали бы то, что находится по тому же адресу в процессе B. Если это одна и та же программа, вам может повезти, и она будет тот же код, но он не будет иметь доступа ни к каким данным, содержащимся в процессе A.

person Mark Ransom    schedule 13.10.2009

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

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

Похоже, что вы хотите на самом деле какую-то систему передачи сообщений или RPC.

person Jack Lloyd    schedule 13.10.2009
comment
да передача сообщения. Уже реализовал один с помощью boost::interprocess, интересовался другими способами - person Maciek; 13.10.2009

Вот почему люди изобрели такие вещи, как COM, RPC и CORBA. Каждый из них дает такую ​​общую возможность. Как вы могли догадаться, каждый делает эту работу немного иначе, чем другие.

Boost IPC на самом деле не поддерживает удаленные вызовы процедур. Это позволит поместить переменную в разделяемую память, чтобы она была доступна для двух процессов, но если вы хотите использовать геттер/сеттер для доступа к этой переменной, вам придется сделать это самостоятельно.

Все это в основном обертки для создания «вкусной» версии того, что вы можете сделать без них. В Windows, например, вы можете самостоятельно поместить переменную в разделяемую память. Вы можете сделать то же самое в Linux. Библиотека Boost является довольно «тонкой» библиотекой, которая позволяет вам писать один и тот же код для Windows или Linux, но не пытается создать много поверх этого. CORBA (например) представляет собой гораздо более толстый слой, обеспечивающий относительно полную распределенную среду.

person Jerry Coffin    schedule 13.10.2009

Если оба процесса находятся в одном приложении, это должно работать. Если вы пытаетесь отправить указатели функций между приложениями, вам не повезло.

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

person Graeme Perrow    schedule 13.10.2009
comment
Другими словами: даже если я использую boost::interpcocess, управляемый сегмент общей памяти (например), то даже если я передам указатель - он все равно не будет работать, верно? - person Maciek; 13.10.2009
comment
Я ничего не знаю о повышении, но не имеет значения, как вы передаете указатели между процессами. Если ваша программа порождает несколько потоков, вы можете передавать указатели между ними. Если вы запускаете два отдельных приложения, вы не можете. - person Graeme Perrow; 13.10.2009
comment
Пожалуйста, поделитесь с нами своим определением процесса и приложения. - person kmarsh; 13.10.2009
comment
Упс, я перепутал процессы и потоки. Мой комментарий правильный, мой ответ нет. Я обновлю. - person Graeme Perrow; 13.10.2009
comment
Непонятно, что вы подразумеваете под одним и тем же приложением. Если они находятся в разных процессах, нет никакой гарантии, что это сработает. Возможно, вы имели в виду, являются ли они разными потоками в одном и том же процессе? В этом случае это может сделать то, что вы хотите. Но ОП совершенно явно указал на отдельные процессы... - person Steven Schlansker; 13.10.2009