2011-02-02 15 views
6

Necesito crear una aplicación de Linux que realice el escaneo de red inalámbrica, coloque el resultado en una estructura y envíela de alguna manera a otra aplicación principal que usará los datos. Mi idea inicial era crear una tubería en la aplicación principal, fork y comenzar otro proceso por execl, que puede escribir en la tubería. Algo como esto:Cómo intercambiar datos binarios entre procesos en Linux

pid_t pid = NULL; 
int pipefd[2]; 
FILE* output; 
char line[256]; 

pipe(pipefd); 
pid = fork(); 
if (pid == 0) 
{ 
// Child 
    close(pipefd[0]); 
    dup2(pipefd[1], STDOUT_FILENO); 
    dup2(pipefd[1], STDERR_FILENO); 
    execl("/sbin/wifiscan", "/sbin/wifiscan", (char*) NULL); 
} 

//Only parent gets here. Listen to what the wifi scan says 
close(pipefd[1]); 
output = fdopen(pipefd[0], "r"); 

while(fgets(line, sizeof(line), output)) 
{ 
//Here we can listen to what wifiscan sends to its standard output 
} 

Sin embargo, esto no funcionará con datos binarios, si el 0 binario aparece en la salida. Así que podría formatear la salida de la aplicación wifiscan en texto, enviarla a canalizar y analizar en la aplicación principal, o hacerlo de forma más inteligente que aún no sé.

¿Cuáles son otros medios para intercambiar datos de manera confiable entre procesos en Linux?

Respuesta

7

sospecho que lo que está sucediendo es que fgets() es la lectura de los caracteres NUL correctamente, pero que estás interpretando el primero como el final de la línea que se ha leído. Es complicado porque fgets() está destinado a la entrada de texto, y utiliza el '\ 0' como un centinela, no devuelve el número de caracteres leídos. Incluso si sabe que cada línea será \n terminada, existe la posibilidad de que los datos binarios sin procesar incrustados en una línea también incluyan un \n. Por lo tanto, cambie a fread(), que es para binario. Puede colocar un tamaño de mensaje de longitud fija (por ejemplo, 2 bytes por 4 bytes) en el frente de cada mensaje para que el otro lado pueda leerlo primero y luego haga un fread() para obtener el tamaño exacto del mensaje, evitando problemas con lecturas parciales de mensajes .

Si realmente desea mantener un extraño híbrido de texto y binarios, se podría tratar de usar ftell() después fgets() para averiguar cuánto más largo de la corriente que eres, y por lo tanto el número de caracteres debe estar en su búfer , pero nunca he visto un sistema serio hacer algo tan hacky.

Para el registro, sin hacer algo marcadamente ineficiente como la codificación hexadecimal de cada carácter en los datos binarios, podría codificar los caracteres molestos. Por ejemplo, las secuencias de escape literales de cadenas C podrían ser utilizadas, con \0 representando un NUL y \\ un solo \. Aunque es menos fácil de verificar visualmente, puede ser más fácil codificar/decodificar programáticamente caracteres no imprimibles usando decir octal \NNN. Si hay muchos caracteres no imprimibles, un enfoque de uuencode de base 64, como el que se usa en los archivos adjuntos de correo electrónico MIME, es otra codificación adecuada pero totalmente no legible.

+1

'ftell()' no es probable que funcione en flujos desechables como tuberías, de todos modos. – caf

+0

Estoy de acuerdo con la construcción de un protocolo básico para sus datos y luego usando 'fread()' en lugar de 'fgets()'. Esta [respuesta] (http://stackoverflow.com/questions/2870549/fifos-implementation/2871538#2871538) a una pregunta sobre [Implementación FIFOs] (http://stackoverflow.com/q/2870549/203667) puede ser de uso adicional ya que proporciona un par de ejemplos sobre cómo se podría implementar dicho protocolo. – jschmier

+0

fread() funciona perfecto. Gracias – Patryk

0

¿Datos de intercambio confiablemente? Esto me hace pensar en la biblioteca 0MQ (ZeroMQ): http://zeromq.org

Eche un vistazo y, como beneficio adicional, sus procesos podrán hablar incluso en computadoras distantes.

Bienvenido a la nube.

2

Normalmente se usaría fread y fwrite para intercambiar estructuras binarias entre procesos. Funciona muy bien para registros de longitud fija, y no hay problemas para enviar nulos, etc.

He descubierto a lo largo de mi larga carrera que en la mayoría de las aplicaciones es mucho mejor intercambiar cadenas ASCII, fácilmente analizables (por ejemplo, scanf), en lugar de datos binarios. De esta forma, los mensajes se pueden observar y registrar, y los procesos individuales pueden probarse mediante telnet y escribiendo (generalmente pegando) en ellos. Simplemente hace que sea más fácil de desarrollar si el programador puede leer el tráfico de mensajes.

Cuestiones relacionadas