2

This is a follow-up question, UNIX-focused, to my previous question here.

I was wondering whether a file descriptor open by a process, could safely be used in forked processes.

I've run a few tests by running several hundreds processes at the same time, all writing continuously to the same file descriptor. I found out that:

  • when fwrite() calls are up to 8192 bytes, all calls are perfectly serialized and the file is OK.
  • when fwrite() calls are more than 8192 bytes, the string is split into 8192 byte chunks that get randomly written to the file, which ends up corrupted.

I tried to use flock(), without success as every process tries to lock/unlock the same file descriptor, which does not make sense. The outcome is the same.

Is there a way to safely share the file descriptor between all the processes, and get all fwrite() calls properly serialized?

4

2 回答 2

3

您需要注意的第一件事是 stdio 缓冲区。因为您使用的是 stdio ( fwrite()) 而不是系统调用 directlr ( write()),所以您不知道数据何时会真正刷新到文件中。要绕过此问题,您必须在每次释放锁之前刷新临界区中的 stdio 缓冲区:

take the lock
fwrite(foo, ...);
fflush(thefile);
release the lock

...或者您可以切换到write()直接使用。

现在,进入主要问题:如何锁定文件,以便一次只有一个进程可以独占访问该文件。

您可能会也可能不会使用flock(). 这取决于不同进程如何获得同一个文件的文件描述符。flock()锁与打开的文件表条目相关联。因为fork()anddup()创建引用相同文件表条目的新文件描述符,从 的角度来看它们是相同的对象,因此在这种情况下flock()您不能使用。flock()另一方面,如果每个进程都open()直接打开自己的文件副本,那么您可以使用flock().

fcntl()-style 锁定不会遇到这个问题(相反,它会遇到不同类型的问题!)。fcntl()锁是每个进程的,因此进程如何将文件描述符获取到同一个文件并不重要。

所以我建议你尝试使用fcntl()-style 锁定:

struct flock ll;

/* lock */
ll.l_start = ll.l_len = ll.l_whence = 0; /* lock the whole file */
ll.l_type = F_WRLCK; /* exclusive lock */
fcntl(fd, F_SETLKW /* or F_SETLK */, &ll);

/* unlock */
ll.l_type = F_UNLCK;
fcntl(fd, F_SETLKW /* or F_SETLK */, &ll);
于 2013-07-04T16:57:38.773 回答
2

您使用文件描述符的方式是非常安全的。写入不同步,因此输出可能不是您所期望的,但没有什么“不安全”的。如果您要问“如何将写入同步到通用文件描述符”,那么答案很明显:使用同步机制。在您描述在多个进程之间共享一个文件描述符的情况下,也许最简单的事情是在第二个管道上传递一个令牌。有一个在所有进程之间共享的管道并将单个字符写入其中。当一个进程想要写入第一个 fd 时,它会尝试从管道中读取一个字符。读取成功后,继续写入(确保刷新),然后将字符写回管道。当任何进程处于临界区时(即,它已读取但尚未写入令牌),任何其他进程都会阻止读取,直到其他进程完成其写入,只要您不要忘记刷新!这是一个相当昂贵的操作,因为它要求每个进程保持两个额外的文件描述符打开,并且可用文件描述符数量的上限相当低,通常在 1024 的数量级上,但它通常非常有效。

于 2013-07-04T21:51:25.410 回答