如何在Linux中的进程之间交换二进制数据

Pat*_*ryk 6 c linux posix fork

我需要创建一个可以进行无线网络扫描的linux应用程序,将结果放入一个结构中并以某种方式将其发送到另一个将使用该数据的主应用程序.我最初的想法是在主应用程序中创建一个管道,fork并通过execl启动另一个进程,它可以写入管道.像这样的东西:

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
}
Run Code Online (Sandbox Code Playgroud)

但是,如果输出中出现二进制0,则无法使用二进制数据.所以我可以将wifiscan应用程序的输出格式化为文本,将其发送到管道并在主应用程序中解析,或者以我还不知道的更智能的方式进行.

在Linux中的进程之间可靠地交换数据的其他方法是什么?

Ton*_*roy 7

我怀疑正在发生的是fgets()正确读取NUL字符,但是您将第一个解释为读取的行的结尾.它很棘手,因为fgets()它用于文本输入,它确实使用'\ 0'作为标记,而不是返回读取的字符数.即使你知道每一行都将被\n终止,也有可能是嵌入在一行中的原始二进制数据也包括在内\n.所以,切换到fread(),这意味着二进制.您可以在每条消息的前面放置一个固定长度(例如2字节,4字节)的消息大小,以便另一方可以先读取该fread()消息,然后针对确切的消息大小执行操作,从而避免部分消息读取出现混乱问题.

如果你真的想保留一些奇怪的文本和二进制混合,你可以尝试使用ftell()after fgets()来找出你的流进一步的数量,因此你的缓冲区应该有多少个字符,但我从未见过严肃的制度做得如此hacky.

对于记录而言,如果没有对二进制数据中的每个字符进行十六进制编码等非常低效的操作,您只需编码麻烦的字符即可.例如,可以使用C字符串文字转义序列,\0表示NUL和\\单个\.虽然不太容易进行视觉检查,但使用say octal编程/解码不可打印的字符可能更容易\NNN.如果有很多不可打印的字符,那么base-64 uuencode方法 - 例如在MIME电子邮件附件中使用 - 是另一种合适但完全不可读的编码.