作用
O_CLOEXEC和FD_CLOEXEC作用:打开的文件描述符在执行exec调用新程序前自动被关闭
- O_CLOEXEC模式下open和标志设置为原子操作,2.6.23后才支持。
- FD_CLOEXEC需单独调用fcntl 设置FD_CLOEXEC,此时open和fcntl两个操作不是原子操作。
- 两种方式下的fd在通过fork调用产生的子进程中均不被关闭。
- 调用dup族类函数得到的新文件描述符将清除O_CLOEXEC模式。
example
int fd = open(file_name, O_RDWR|O_CLOEXEC, S_IRUSR);
or
int fd = open(file_name, O_RDWR, S_IRUSR);
int val = fcntl(fd, F_GETFD);
if (val > 0) {
fcntl(fd, F_SETFD, val | FD_CLOEXEC);
内核实现
这里主要简单介绍一下内核是如何利用这个标志,在exec的哪个位置关闭文件,内核调用路径如下
单内核在加载一个可执行文件时,调用路径如下
load_elf_binary
setup_new_exec(bprm)
do_close_on_exec(struct files_struct *files)
void do_close_on_exec(struct files_struct *files)
{
unsigned i;
struct fdtable *fdt;
/* exec unshares first */
spin_lock(&files->file_lock);
for (i = 0; ; i++) {
unsigned long set;
unsigned fd = i * BITS_PER_LONG;
fdt = files_fdtable(files);
if (fd >= fdt->max_fds)
break;
set = fdt->close_on_exec[i];
if (!set)
continue;
fdt->close_on_exec[i] = 0;
for ( ; set ; fd++, set >>= 1) {
struct file *file;
if (!(set & 1))
continue;
file = fdt->fd[fd];
if (!file)
continue;
rcu_assign_pointer(fdt->fd[fd], NULL);
__put_unused_fd(files, fd);
spin_unlock(&files->file_lock);
filp_close(file, files);
cond_resched();
spin_lock(&files->file_lock);
}
}
spin_unlock(&files->file_lock);
}
网友评论