dup()后跟多个线程或进程的close()

时间:2013-06-02 09:20:37

标签: c linux file-descriptor multiprocess

我的程序按时间顺序执行以下操作

  1. 程序以root权限启动。
  2. 在其他任务中,仅具有root权限的文件是open() ed。
  3. 删除root权限。
  4. 生成子进程clone()并设置CLONE_FILES | CLONE_FS | CLONE_IO标志,这意味着虽然它们使用单​​独的虚拟内存区域,但它们共享相同的文件描述符表(以及其他IO内容)。 / LI>
  5. 所有子进程execve()他们自己的程序(不使用FD_CLOEXEC标志)。
  6. 原始程序终止。
  7. 现在我希望每个衍生程序都读取上述文件的内容,但是在他们都读完文件之后,我希望它被关闭(出于安全原因)。

    我正在考虑的一个可能的解决方案是进行步骤3a,其中每个子进程的文件的fd为dup()一次,并且每个子进程都有自己的fd(作为argv )。然后每个子程序只需close()他们的fd,这样在指向文件的所有fds为close()之后,“实际文件”就会关闭。

    但这样做有用吗?这样做是否安全(即文件是否真的关闭)?如果没有,还有其他/更好的方法吗?

1 个答案:

答案 0 :(得分:2)

正如我上面提到的那样使用dup()可能就好了,我现在 - 在问这个问题后的第二天 - 意识到有一个更好的方法可以做到这一点,至少从这一点来看线程安全的观点。

所有dup()合法文件描述符指向相同的文件位置指示符,这当然意味着当多个线程/进程可能同时尝试在读取操作期间更改文件位置时遇到麻烦(即使您自己的代码以线程安全的方式执行,同样不一定适用于您所依赖的库。

等等,为什么不在需要的文件上多次调用open()(每个孩子一次),然后再删除root?来自open()的手册:

  

对open()的调用会创建一个新的打开文件描述,这是系统范围的打开文件表中的一个条目。此条目记录文件偏移量和文件状态标志(可通过fcntl(2)F_SETFL操作修改)。文件描述符是对这些条目之一的引用;如果随后删除或修改路径名以引用其他文件,则此引用不受影响。新的打开文件描述最初不与任何其他进程共享,但可以通过fork(2)进行共享。

可以像这样使用:

int fds[CHILD_C];
for (int i = 0; i < CHILD_C; i++) {
    fds[i] = open("/foo/bar", O_RDONLY);
    // check for errors here
}
drop_privileges();
// etc

然后每个孩子通过argv获得对其中一个fds的引用,并执行以下操作:

  1. FILE *stream = fdopen(atoi(argv[FD_STRING_I]), "r")
  2. stream
  3. 中读取所需内容
  4. fclose(stream)(这也会关闭基础文件描述符)
  5. 免责声明:根据我所运行的一系列测试,这确实是安全可靠的。然而,我只用 O_RDONLY 测试了open()使用O_RDWR或O_WRONLY可能安全,也可能不安全