Documentation 📑 filp_close 的 async 逻辑 § VFS 关闭文件的逻辑并不是顺序执行的,而是存在一个 delay 操作: int filp_close(struct file *filp, fl_owner_t id) { int retval; retval = filp_flush(filp, id); // flush operation, call filp->f_op->flush fput(filp); // real close logic return retval; } EXPORT_SYMBOL(filp_close); void fput(struct file *file) { if (atomic_long_dec_and_test(&file->f_count)) { struct task_struct *task = current; if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { init_task_work(&file->f_rcuhead, ____fput); // <- real task if (!task_work_add(task, &file->f_rcuhead, TWA_RESUME)) return; /* * After this task has run exit_task_work(), * task_work_add() will fail. Fall through to delayed * fput to avoid leaking *file. */ } // put task to workqueue if (llist_add(&file->f_llist, &delayed_fput_list)) schedule_delayed_work(&delayed_fput_work, 1); // 1 is delayed jiffies } } 然而,对于真正的 close 系统调用,却并不使用这样的 delay 逻辑: SYSCALL_DEFINE1(close, unsigned int, fd) { int retval; struct file *file; file = close_fd_get_file(fd); if (!file) return -EBADF; retval = filp_flush(file, current->files); /* * We're returning to user space. Don't bother * with any delayed fput() cases. */ __fput_sync(file); // <- __fput_sync 是同步操作,没有delay /* can't restart close syscall because file table entry was cleared */ if (unlikely(retval == -ERESTARTSYS || retval == -ERESTARTNOINTR || retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK)) retval = -EINTR; return retval; }