2009-12-23 10 views
5

En el tutorial proporcionado en: http://www.erlang.org/doc/tutorial/cnode.htmlErlang C nodo relacionado pregunta

Está el ejemplo siguiente:


/* cnode_s.c */ 
#include 
#include 
#include 
#include 
#include "erl_interface.h" 
#include "ei.h" 
#define BUFSIZE 1000 
int main(int argc, char **argv) { 
    int port;        /* Listen port number */ 
    int listen;        /* Listen socket */ 
    int fd;         /* fd to Erlang node */ 
    ErlConnect conn;       /* Connection data */ 
    int loop = 1;       /* Loop flag */ 
    int got;         /* Result of receive */ 
    unsigned char buf[BUFSIZE];    /* Buffer for incoming message */ 
    ErlMessage emsg;       /* Incoming message */ 
    ETERM *fromp, *tuplep, *fnp, *argp, *resp; 
    int res; 
    port = atoi(argv[1]); 
    erl_init(NULL, 0); 
    if (erl_connect_init(1, "secretcookie", 0) == -1) 
    erl_err_quit("erl_connect_init"); 
    /* Make a listen socket */ 
    if ((listen = my_listen(port))

Sospecho que erl_receive_msg es una llamada de bloqueo, y no sé cómo superar esto En la programación en red C hay una declaración "select" pero en la API Erlang EI no sé si existe tal declaración.

Básicamente quiero construir un nodo C, que continuamente envía mensajes a los nodos Erlang. Por simplicidad, supongamos que solo hay un nodo de Erlang.

El nodo de Erlang tiene que procesar los mensajes que recibe del nodo C. Se supone que el nodo Erlang no garantiza que ha recibido el mensaje, no tiene que responder con el resultado del procesamiento. Por lo tanto, una vez que se envía el mensaje, no me importa la fe.

Uno podría pensar que se podría modificar el código como:

... 
if (emsg.type == ERL_REG_SEND) { 
    ... 
    while(1) { 
     //generate tuple 
     erl_send(fd, fromp, tuple); 
     //free alloc resources 
    } 
    ... 
} 

Esto producirá un bucle infinito en el que se produce y consume (enviar) mensajes. Pero hay un problema importante: si hago esto, entonces el nodo C podría enviar demasiados mensajes al nodo Erlang (por lo que debería haber una forma de enviar un mensaje desde el nodo Erlang al nodo C para reducir la velocidad), o el nodo Erlang podría pensar que el nodo C está inactivo.

sé que las preguntas deben ser cortas una suite (esto es largo y feo), pero resumiendo:

¿Qué mecanismo (llamada a procedimiento, algoritmo) se podría utilizar para desarrollar un productor ansiosos en C para una ¿consumidor perezoso en Erlang, de modo que ambas partes son conscientes del contexto subyacente?

Respuesta

2

Uso los controladores de puerto yo mismo para el caso que está describiendo (no he tocado los nodos C porque prefiero tener más desacoplamiento).

Eche un vistazo a la biblioteca Port Driver para Erlang: EPAPI. Hay un proyecto que aprovecha esta biblioteca: Erland DBus.

+0

El problema es que el productor será el nodo C y el nodo Erlang será el consumidor. He considerado la idea de usar un puerto, pero llamar en un bucle continuo al servicio del controlador del puerto no parece la mejor manera de hacerlo. – user237855

+0

@zalmoxis: hay muchas maneras diferentes de abordar esta situación, una de las cuales podría ser utilizar un "algoritmo de crédito basado en tokens". El "nodo consumidor" envía "créditos" al nodo productor. Cada "envío" requiere un "crédito": cuando no hay más, el "productor" debe esperar una próxima "entrega" de créditos. – jldupont

+0

@zalmoxis: el "shaper basado en token" que describo anteriormente puede implementarse fácilmente en el lado del "productor" (escrito en C), mientras que es igualmente trivial agregar soporte para este esquema en el lado de Erlang. Debido a que ya está en "dolor" usando "C nodos", entonces sé que puede asumir los Controladores de puerto. Saludos y diviértete! (de todos modos, como siempre, considere mi contribución como una sugerencia para su consideración). – jldupont

1

¿Revisó la función ei_receive_msg_tmo? Supongo que funciona de manera similar al constructo de recepción de Erlang, por lo que si establece el tiempo de espera en 0, será no bloqueante.

Creo que erl_interface está en desuso, y debería usarse ei en su lugar. Esto podría ser una información errónea completa ...

+0

Gracias, actualmente estoy probándolo. Tenga en cuenta que al llamar a ei_receive_msg_tmo con timeout 0 se convertirá en bloqueo. – user237855

+0

Bien. Entonces, aparentemente, las funciones que no son de tiempo de espera caen nuevamente a las de tiempo de espera con ms = 0. Es por eso que ms = 0 se vuelve bloqueante (vea la función ei_read_t() interfaz_herl/src/misc/ei_portio.c). Yo llamaría a esto una victoria de la pereza sobre la funcionalidad :) – Zed

1

necesita echar un vistazo más de cerca al enlace del tutorial que ha publicado. (busque "Y finalmente tenemos el código para el cliente de nodo C"). Verá que el autor proporcionó una implementación de cnode de cliente. Parece racional.