2009-10-13 19 views
7

Soy consciente de que cada proceso crea su propio espacio de direcciones de memoria, sin embargo, me preguntaba,¿Es posible utilizar punteros de función en los procesos?

Si el Proceso A era tener una función como:

int DoStuff() { return 1; } 

y un puntero typedef como:

typedef int(DoStuff_f*)(); 

y una función getter como:

DoStuff_f * getDoStuff() { return DoStuff; } 

y una forma mágica para comunicarse con el Procedimiento B a través de ... dicen impulso :: entre procesos

sería posible pasar el puntero de función para procesar B y llame

Proceso de un DoStuff directamente desde el Proceso B?

+2

Indique el O/S con el que está tratando. La respuesta a la pregunta es muy diferente para vxWorks versus Linux. – kmarsh

+2

De acuerdo: todas las respuestas "no" deben entenderse como "no portables" y/o "no en mi sistema operativo". En algunas plataformas con sistemas operativos muy livianos no hay memoria protegida, y simplemente funcionará. –

+0

Supongo que es Windows. Mi suposición se basa en las primeras preguntas de Maciek y el estilo de nombramiento de funciones :) –

Respuesta

8

No. Todos los punteros de una función es una dirección en el espacio de direcciones de su proceso. No tiene un marcador intrínseco que sea exclusivo de diferentes procesos. Por lo tanto, incluso si su puntero de función que acaba de pasar a ser válido una vez que haya sido movido a B, sería llamar a esa función en nombre de B. Proceso de

Por ejemplo, si usted tenía

////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! 

Si los procesos A y B están ejecutando el mismo código, puede terminar con funciones idénticas en direcciones idénticas, ¡pero seguirá trabajando con las estructuras de datos y la memoria global de B! Entonces la respuesta corta es, no, ¡así no es como quieres hacer esto!

Además, medidas de seguridad como address space layout randomization pueden evitar que este tipo de "trucos" funcionen.

Estás confundiendo IPC y RPC. IPC es para comunicar datos, como sus objetos o una burbuja de texto. RPC es para hacer que el código se ejecute en un proceso remoto.

+0

+1 para ASLR - Estaba intentando recordar detalles sobre eso. –

0

Si ambos procesos están en la misma aplicación, entonces esto debería funcionar. Si está tratando de enviar punteros de función entre aplicaciones, entonces no tiene suerte.

Mi respuesta original fue correcta si supone que un proceso y un hilo son la misma cosa, que no lo son. Las otras respuestas son correctas: los diferentes procesos no pueden compartir punteros de función (o cualquier otro tipo de punteros, para el caso).

+0

por lo que en otras palabras: incluso si uso boost :: interpcocess, segmento de memoria compartida administrada (por ejemplo), incluso si paso el puntero - Todavía no funciona, ¿correcto? – Maciek

+1

No sé nada sobre el impulso, pero no importa cómo se comunican los indicadores entre los procesos. Si su programa genera múltiples hilos, puede pasar punteros entre ellos. Si está iniciando dos aplicaciones por separado, no puede. –

+0

Por favor, comparta con nosotros su definición de "proceso" frente a "aplicación". – kmarsh

8

En resumen, no puede usar el puntero de función que pasó a otro proceso.

Los códigos de función se encuentran en páginas de memoria protegidas, no puede escribir en ellas. Y cada proceso tiene espacio de direcciones virtuales aislado, por lo que la dirección de la función no es válida en otro proceso. En Windows, puede utilizar la técnica descrita en el artículo this para insertar su código en otro proceso, pero la última versión de Windows lo rechaza.

En lugar de pasar el puntero a la función, debería considerar crear una biblioteca que se usará en ambos procesos. En este caso, podría enviar un mensaje a otro proceso cuando necesite llamar a esa función.

1

Si trataste de utilizar el puntero de función del proceso A del proceso B, no estarías llamando al proceso A; llamarías a cualquier cosa que esté en la misma dirección en el proceso B. Si son el mismo programa, podrías tener suerte y será el mismo código, pero no tendrá acceso a ninguno de los datos contenidos en el proceso A.

1

Un puntero a la función no funcionará para esto, ya que solo contiene la dirección inicial para el código; si el código en cuestión no existe en el otro proceso, o (debido a algo como la aleatorización del espacio de direcciones) está en una ubicación diferente, el puntero de la función será inútil; en el segundo proceso, señalará algo, o nada, pero casi con certeza, no donde usted lo desee.

Usted podría, si usted estaba loco^Wdaring, copiar la secuencia de instrucciones reales en la memoria compartida y luego hacer que el segundo proceso salte directamente a la misma, pero incluso si pudiera hacer que esto funcione, la función todavía se ejecutará Proceso B, no Proceso A.

Parece que lo que desea es en realidad algún tipo de sistema de paso de mensajes o RPC.

+0

sí pasa el mensaje. Ya implementado uno usando boost :: interprocess, se preguntaba sobre "otras formas" – Maciek

1

Es por eso que la gente ha inventado cosas como COM, RPC y CORBA. Cada uno de ellos brinda este tipo de capacidad general. Como diría, cada uno hace el trabajo un poco diferente de los demás.

Boost IPC realmente no admite llamadas a procedimientos remotos. Permitirá poner una variable en memoria compartida, de modo que sea accesible para dos procesos, pero si desea utilizar un getter/setter para acceder a esa variable, tendrá que hacerlo usted mismo.

Esas son básicamente envolturas para producir una versión "apetecible" de algo que puedes hacer sin ellas. En Windows, por ejemplo, puede poner una variable en la memoria compartida por su cuenta. Puedes hacer lo mismo en Linux. La biblioteca Boost es una biblioteca bastante "delgada" que permite escribir el mismo código para Windows o Linux, pero no trata de construir mucho además de eso. CORBA (para un ejemplo) es una capa mucho más gruesa, que proporciona un entorno distribuido relativamente completo.

Cuestiones relacionadas