- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
This manpage对于 dup2
系统调用说:
EBUSY (Linux only) This may be returned by dup2() or dup3() during a race condition with open(2) and dup().
它讨论的竞争条件是什么?如果 dup2
出现 EBUSY
错误,我该怎么办?我应该像 EINTR
那样重试吗?
最佳答案
在fs/file.c
中有解释,do_dup2()
:
/*
* We need to detect attempts to do dup2() over allocated but still
* not finished descriptor. NB: OpenBSD avoids that at the price of
* extra work in their equivalent of fget() - they insert struct
* file immediately after grabbing descriptor, mark it larval if
* more work (e.g. actual opening) is needed and make sure that
* fget() treats larval files as absent. Potentially interesting,
* but while extra work in fget() is trivial, locking implications
* and amount of surgery on open()-related paths in VFS are not.
* FreeBSD fails with -EBADF in the same situation, NetBSD "solution"
* deadlocks in rather amusing ways, AFAICS. All of that is out of
* scope of POSIX or SUS, since neither considers shared descriptor
* tables and this condition does not arise without those.
*/
fdt = files_fdtable(files);
tofree = fdt->fd[fd];
if (!tofree && fd_is_open(fd, fdt))
goto Ebusy;
看起来像 EBUSY
当要释放的描述符处于某种不完整状态时它仍在打开时返回(fd_is_open
但不存在于 fdtable
)。
编辑(更多信息并想要赏金)
为了理解 !tofree && fd_is_open(fd, fdt)
是如何发生的,让我们看看文件是如何打开的。这是 sys_open
的简化版本:
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
/* ... irrelevant stuff */
/* allocate the fd, uses a lock */
fd = get_unused_fd_flags(flags);
/* HERE the race condition can arise if another thread calls dup2 on fd */
/* do the real VFS stuff for this fd, also uses a lock */
fd_install(fd, f);
/* ... irrelevant stuff again */
return fd;
}
基本上发生了两件非常重要的事情:分配了一个文件描述符,然后它才真正被 VFS 打开。这两个操作修改了进程的fdt
。他们都使用锁,所以在这两个调用中没有什么不好的。
为了记住哪些fds
被分配了一个名为open_fds
的位 vector 被fdt
使用。在 get_unused_fd_flags()
之后,fd
已经分配,并且在 open_fds
中设置了相应的位。 fdt
上的锁已被释放,但真正的 VFS 工作尚未完成。
此时,另一个线程(或共享 fdt
情况下的另一个进程)可以调用 dup2,因为锁已被释放而不会阻塞。如果 dup2
在此处采用其正常路径,则 fd
将被替换,但 fd_install
仍将为旧文件运行。因此检查并返回 Ebusy
。
我在 fd_install()
的评论中找到了关于此竞争条件的更多信息,这证实了我的解释:
/* The VFS is full of places where we drop the files lock between
* setting the open_fds bitmap and installing the file in the file
* array. At any such point, we are vulnerable to a dup2() race
* installing a file in the array before us. We need to detect this and
* fput() the struct file we are about to overwrite in this case.
*
* It should never happen - if we allow dup2() do it, _really_ bad things
* will follow. */
关于c - 使用 dup2 时的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23440216/
我有一个 excel 文件,我需要进行一些更改。我需要识别重复项,然后将“1st”放在第一个 dup 的系列列中。对于其余的重复需要在系列列中放置“其他重复”。可能吗?我尝试了查找和匹配,但没有任何帮
我是一个C初学者,尝试使用dup(),我写了一个程序来测试这个函数,结果和我预期的有点不同。 代码: // unistd.h, dup() test #include #include #incl
我正在尝试创建两个子进程: 一个子进程从文件中读取输入(该文件作为参数传入),并将输出写入管道。 另一个子进程从管道读取其输出并将其输出写入文件,该文件也作为参数传入。 父级为子级设置一些文件描述符,
当我们使用 dup 将 STDOUT 重定向到我们做的管道时: close(1); dup(fd[1]); close(fd[0]); close(fd[1]); execlp("ls","-al",
因此,我阅读了有关 Linux 中的文件 I/O 的内容,并想尝试一下。然而,我在代码中遇到了两个奇怪的行为,我正在努力寻找它们的原因。 /* * This program shows the us
我想知道为什么 dup 总是在下面的代码中返回零(其中一个文件被打开,而不是连续完成 10 个 dup): #include #include #include #include #inclu
我正在开发一个程序,要求用户输入 s、f 或 0 作为用户输入。 S 向系统打印预定义消息,f 将该预定义消息写入用户作为参数提供的文件。 0 终止程序。 我需要让程序只有一个写入标准输出的写入语句。
我正在在线学习算法类(class),我正在尝试计算数字列表中的最大成对乘积。这个问题之前已经回答过: maximum pairwise product fast solution和 Python fo
我想知道为什么以下字节码中的异常(用于抛出异常)是重复的。 NEW java/lang/IllegalArgumentException DUP INVOKESPECIAL java/lang/Ill
我正在编写代码以将 stdout 重定向到一个文件(例如 ls 返回到一个文件的结果)并且 dup2() 函数不重定向我的输出。这是我的代码: void testDup() { int new
close(fileno(stdout)); int fd = dup(fileno(stdin)); //printf("Hello World\n"); write(fd, "Hell
目前我只是在一个使用 java 字节码的项目中。我通常看到,当创建一个新的类实例并在其上调用一个方法时,字节码将是这样的: NEW DUP INVOKESPECIAL > 这里为什么要做“DUP”?
当涉及到复制文件描述符时,我能得到一个关于 dup() 函数的非常简单的解释吗?我想使用管道,但我还必须让 child 从管道中读取(这是简单的部分),但将数据写回父级。我应该使用另一根管道,还是可以
>> a = 5 => 5 >> b = "hello, world!" => "hello, world!" >> b.dup => "hello, world!" >> a.dup TypeErr
我对这个用于教育目的的小代码有疑问。我不明白它是如何工作的。 #include #include #define FNAME "info.txt" #define STDIN 0 int main
Java字节码指令集提供various forms of dup instruction 。我无法理解这些指令和 swap 指令的用途。哪些 Java 代码在编译时会使用这些指令生成字节码? 最佳答案
鉴于以下信息,我如何在唯一的 params 和 cron_action_id 对上选择最新的订单项(基于 time_entered)还没被处决吗? cron_schedule 例如,id 1、2和4具
int mypipe[2]; pipe(mypipe); int dupstdout=dup2(mypipe[1],1); cout<<"hello";//not printed on termina
我一直想创建一个 fork 两次以创建两个子进程的子进程。随着一个的输出,发送到另一个。我找到了这个示例代码。但我对它的工作原理感到困惑。 我找到了一个 example here .但我对 dup 的
所以我尝试使用 dup() 将标准输出重定向到一个文件。 int save_fd; save_fd=dup(1); //saves the current stdout close(1); //clo
我是一名优秀的程序员,十分优秀!