通过文件描述符(fd)而不是文件名来比较/比较两个文件

Linux中有没有办法,使用生成存储在内存中的两个文件的差异/补丁,使用通用格式(即:统一差异,与命令行差异实用程序一样)?

我正在开发一个系统,我在内存中生成两个文本文件,没有可用的外部存储空间.我需要创建两个文件的逐行diff,因为它们是mmap,所以它们没有文件名,这使我无法简单地调用system(“diff file1.txt file2.txt”).

我有文件描述符(fds)可供使用,这是我唯一的数据入口点.有没有办法通过比较两个打开的文件生成差异/补丁?如果实现是MIT / BSD许可(即:非GPL),那就更好了.

谢谢.

最佳答案
考虑到要求,最好的选择是实现自己的内存中diff -au.您可以根据需要调整OpenBSD diff的相关部分.

下面是一个如何通过管道使用/usr/bin/diff命令来获取存储在内存中的两个字符串之间的统一差异的概述:

>创建三个管道:I1,I2和O.
>分叉儿童过程.
>在子进程中:

>将管道I1和I2的读取端移动到描述符3和4,将管道O的写入端移动到描述符1.
>在子进程中关闭这些管道的另一端.打开描述符0用于从/ dev / null读取,而描述符2用于写入/ dev / null.
>执行execl(“/usr/bin/diff”,“diff”,“ – au”,“/ proc / self / fd / 3”,“/ proc / self / fd / 4”,NULL);

这将在子进程中执行diff二进制文件.它将读取两个管道I1和I2的输入,并将差异输出到管道O.

>父进程关闭I1和I2管道的读取端以及O管道的写入端.
>父进程将比较数据写入I1和I2管道的写入端,并从O管道的读取端读取差异.

请注意,父进程必须使用select()poll()或类似方法(最好使用非阻塞描述符)以避免死锁. (如果父和子同时尝试读取或同时写入,则会发生死锁.)通常,父进程必须不惜一切代价避免阻塞,因为这可能会导致死锁.

当输入数据已完全写入时,父进程必须关闭管道的相应写端,以便子进程检测到输入结束. (除非发生错误,否则必须在子进程关闭O管道末尾之前关闭写入结束.)

当父进程注意到O管道中没有更多数据可用时(read()返回0),它已经关闭了I1和I2管道的写入端,或者出现了错误.如果没有错误,则数据传输完成,并且可以获得子进程.
>父进程使用例如子进程收回子进程. waitpid函数().请注意,如果存在任何差异,则diff将返回退出状态1.

您可以使用第四个管道从子进程接收标准错误流; diff通常不会输出任何标准错误.

您可以使用第五个管道,在子节点中使用fcntl()写入标记为O_CLOEXEC的结尾,以检测execl()错误. O_CLOEXEC标志表示在执行另一个二进制文件时关闭描述符,因此父进程可以通过检测读取结束中的数据结束(read()返回0)来检测diff命令的成功启动.如果execl()失败,那么孩子可以例如将errno值(作为十进制数或int作为)写入此管道,以便父进程可以读取失败的确切原因.

总之,完整的方法(记录标准错误,并检测exec错误)使用10个描述符.这不应该是正常应用程序中的问题,但可能很重要 – 例如,考虑面向Internet的服务器,其中包含传入连接使用的描述符.

转载注明原文:通过文件描述符(fd)而不是文件名来比较/比较两个文件 - 代码日志