Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
来自多个线程或进程的dup()后跟close()_C_Linux_File Descriptor_Multiprocess - Fatal编程技术网

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

来自多个线程或进程的dup()后跟close(),c,linux,file-descriptor,multiprocess,C,Linux,File Descriptor,Multiprocess,我的程序按时间顺序执行以下操作 程序以root权限启动 在其他任务中,只有根权限才能读取的文件是open()ed 根权限被删除 子进程是使用clone()和clone_文件| clone_FS | clone_IO标志集生成的,这意味着当它们使用不同的虚拟内存区域时,它们共享相同的文件描述符表(和其他IO内容) 所有子进程execve()它们自己的程序(不使用FD\u CLOEXEC标志) 原始程序终止 现在,我希望每个生成的程序都读取上述文件的内容,但在它们都读取了该文件之后,我希望它被关闭(

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

  • 程序以root权限启动
  • 在其他任务中,只有根权限才能读取的文件是
    open()
    ed
  • 根权限被删除
  • 子进程是使用
    clone()
    clone_文件| clone_FS | clone_IO
    标志集生成的,这意味着当它们使用不同的虚拟内存区域时,它们共享相同的文件描述符表(和其他IO内容)
  • 所有子进程
    execve()
    它们自己的程序(不使用
    FD\u CLOEXEC
    标志)
  • 原始程序终止
  • 现在,我希望每个生成的程序都读取上述文件的内容,但在它们都读取了该文件之后,我希望它被关闭(出于安全原因)

    我现在考虑的一个可能的解决方案是使用步骤3a,其中文件的fd为
    dup()
    对每个子进程应用一次,并且每个子进程都有自己的fd(作为
    argv
    )。然后每个子程序都会简单地
    close()
    它们的fd,这样在所有指向文件的fd都
    close()
    d之后,“实际文件”就会关闭

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

    当我像上面建议的那样使用
    dup()
    可能还可以,我现在——在问了这个问题一天后——意识到有一种更好的方法可以做到这一点,至少从线程安全的角度来看是这样的

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

    等等,为什么不在删除root之前对所需文件多次调用
    open()
    (每个子文件一次)?参见
    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
    
    intfds[CHILD_C];
    for(int i=0;i
    然后每个孩子通过
    argv
    获得对其中一个FD的引用,并执行如下操作:

  • FILE*stream=fdopen(atoi(argv[FD\u STRING\u I]),“r”)
  • 流中读取所需内容
  • fclose(流)
    (这也会关闭底层文件描述符)

  • 免责声明:根据我运行的一系列测试,这确实是安全可靠的。然而,我只测试了
    open()
    ing withO_RDONLY使用O_RDWR或O_WRONLY可能安全,也可能不安全

    如果父母和孩子都关闭了他们的fd,那么文件就关闭了。是否有任何理由使用
    克隆
    ?我认为一个简单的
    分叉
    会表现出几乎相同的行为。
    如果父母和孩子都关闭了他们的fdldren都关闭他们的fd,然后文件就关闭了。
    这将是个好消息,谢谢。
    有什么理由使用clone吗?我认为一个简单的fork会表现出几乎相同的行为。
    是的,但我使用
    clone()
    的原因与性能有关:所有子程序都需要处理相同的非常大的套接字集(通过
    epoll
    )。共享fd表可以避免不必要的开销。我在问题中提到这一点的原因是,我不是100%认为这个细节无关紧要。它是一个读取(/parse)的选项吗父进程中的文件,并将结果存储在与
    mmap
    共享的内存中,作为步骤3a?这将跳过将fd传递给子进程的问题,并遵守尽快删除特权的原则。是的,我考虑过,但因为文件的内容是敏感的(SSL私钥),将其存储在共享内存中对我来说似乎是个坏主意,因为其他进程可以访问该内存(至少在很短的时间内),因为共享内存需要在删除根后创建(否则
    execve()
    d子进程将无法访问它)。我不太明白。fd现在也可以被其他进程(子进程)看到。我理解您的困境,但在您当前的设置中,无论它是如何实现的,您都必须与子进程共享一个秘密,并信任它们在执行其他程序之前擦除它。