linux内核中的⽂件描述符(三)--fd的回收
linux内核中的⽂件描述符(三)--fd的回收
Kernel version:2.6.14
CPU architecture:ARM920T
1.close函数
上图说明了close(fd)的执⾏过程,主要包括两部分:释放⽂件描述符fd,关闭⽂件file。
//fs/open.c
asmlinkage long sys_close(unsigned int fd)
{
linux内核文件放在哪struct file * filp;
struct files_struct *files = current->files;//获得当前进程的files结构
struct fdtable *fdt;
spin_lock(&files->file_lock);
fdt = files_fdtable(files);//通过进程的打开⽂件列表获得⽂件描述符位图结构
if (fd >= fdt->max_fds)
goto out_unlock;
filp = fdt->fd[fd];
if (!filp)
goto out_unlock;
rcu_assign_pointer(fdt->fd[fd], NULL);
FD_CLR(fd, fdt->close_on_exec);
__put_unused_fd(files, fd);//释放⽂件描述符
spin_unlock(&files->file_lock);
return filp_close(filp, files);//关闭⽂件
out_unlock:
spin_unlock(&files->file_lock);
return -EBADF;
}
2.释放⽂件描述符__put_unused_fd
static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
{
struct fdtable *fdt = files_fdtable(files);
__FD_CLR(fd, fdt->open_fds);//清除位图中的相应标记
if (fd < fdt->next_fd)
fdt->next_fd = fd;//如果释放的fd⼩于next_fd,则next_fd = fd,下次分配从next_fd开始。
//因此释放⼀个fd后,再打开或创建⼀个⽂件放回的可能还是刚释放的fd
}
3.关闭⽂件filp_close
int filp_close(struct file *filp, fl_owner_t id)
{
int retval = 0;
if (!file_count(filp)) {
printk(KERN_ERR "VFS: Close: file count is 0\n");
return 0;
}
if (filp->f_op && filp->f_op->flush)
retval = filp->f_op->flush(filp);
dnotify_flush(filp, id);
locks_remove_posix(filp, id);
fput(filp);
return retval;
}
filp_close函数调⽤fput,在fput中调⽤release函数。
//fs/file_table.c
void fastcall fput(struct file *file)
{
if (rcuref_dec_and_test(&file->f_count))
__fput(file);
}
void fastcall __fput(struct file *file)
{
struct dentry *dentry = file->f_dentry;
struct vfsmount *mnt = file->f_vfsmnt;
struct inode *inode = dentry->d_inode;
might_sleep();
fsnotify_close(file);
/
*
* The function eventpoll_release() should be the first called
* in the file cleanup chain.
*/
eventpoll_release(file);
locks_remove_flock(file);
if (file->f_op && file->f_op->release)
file->f_op->release(inode, file);//在这⾥调⽤release函数。在socket中即socket_close函数 security_file_free(file);
if (unlikely(inode->i_cdev != NULL))
cdev_put(inode->i_cdev);
fops_put(file->f_op);
if (file->f_mode & FMODE_WRITE)
put_write_access(inode);
file_kill(file);
file->f_dentry = NULL;
file->f_vfsmnt = NULL;
file_free(file);
dput(dentry);
mntput(mnt);
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。