详解sys_close

来源:互联网 发布:单片机毕业设计网 编辑:程序博客网 时间:2024/05/19 05:02

    内核源码:linux-2.6.38.8.tar.bz2

    目标平台:ARM体系结构

 

    在Linux内核中,系统调用close的定义如下所示:

/* fs/open.c */SYSCALL_DEFINE1(close, unsigned int, fd){struct file * filp;struct files_struct *files = current->files;struct fdtable *fdt;int retval;spin_lock(&files->file_lock);fdt = files_fdtable(files);if (fd >= fdt->max_fds) //无效的文件描述符goto out_unlock;filp = fdt->fd[fd]; //获得文件指针if (!filp) //filp为NULLgoto out_unlock;rcu_assign_pointer(fdt->fd[fd], NULL); //将fdt->fd[fd]置零FD_CLR(fd, fdt->close_on_exec); //清除相应的close_on_exec比特位__put_unused_fd(files, fd); //清除相应的open_fds比特位spin_unlock(&files->file_lock);retval = filp_close(filp, files); //执行close的主要操作if (unlikely(retval == -ERESTARTSYS ||     retval == -ERESTARTNOINTR ||     retval == -ERESTARTNOHAND ||     retval == -ERESTART_RESTARTBLOCK))retval = -EINTR;return retval;out_unlock:spin_unlock(&files->file_lock);return -EBADF;}
    filp_close函数用于完成close系统调用的主要操作。源代码如下所示:

/* include/linux/fs.h */typedef struct files_struct *fl_owner_t;/* fs/open.c */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) //flush函数指针为真则调用它retval = filp->f_op->flush(filp, id);dnotify_flush(filp, id); //对于目录文件,释放dnotify mark资源locks_remove_posix(filp, id); //清除POSIX文件锁fput(filp);return retval;}
    fput函数在文件指针引用计数file->f_count为零时释放在open等系统调用中所使用的资源。源代码如下所示:

/* fs/file_table.c */void fput(struct file *file){if (atomic_long_dec_and_test(&file->f_count)) //引用计数为零则执行__fput函数销毁文件指针__fput(file);}static void __fput(struct file *file){struct dentry *dentry = file->f_path.dentry;struct vfsmount *mnt = file->f_path.mnt;struct inode *inode = dentry->d_inode;might_sleep(); //可能休眠并记录相应信息以便调试fsnotify_close(file); //实现文件系统事件监控的IN_CLOSE_WRITE或IN_CLOSE_NOWRITE事件eventpoll_release(file); //释放epoll资源locks_remove_flock(file); //清除flock文件锁if (unlikely(file->f_flags & FASYNC)) { //标志FASYNC通过fcntl系统调用设置if (file->f_op && file->f_op->fasync) //当fasync函数指针为真时则调用它,执行异步通知file->f_op->fasync(-1, file, 0);}//当release函数指针为真时则调用它,执行与file->f_op->open相反的操作if (file->f_op && file->f_op->release)file->f_op->release(inode, file);security_file_free(file); //安全模块检查ima_file_free(file); //释放相应i节点的IMA数据if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) //字符设备文件cdev_put(inode->i_cdev);//处理操作函数模块(当以模块加载时),递增file->f_op->owner->refptr->decs计数,并唤醒等待该模块的进程fops_put(file->f_op); put_pid(file->f_owner.pid); //释放捕捉SIGIO信号的进程的相关资源file_sb_list_del(file); //从超级块文件指针链表中移除该项if (file->f_mode & FMODE_WRITE)//递减一些相关的引用计数并将file->f_mnt_write_state从FILE_MNT_WRITE_TAKEN状态更改为FILE_MNT_WRITE_RELEASEDdrop_file_write_access(file); file->f_path.dentry = NULL;file->f_path.mnt = NULL;file_free(file); //释放file->f_cred和文件指针自身dput(dentry); //释放相应的目录项资源(引用计数为零时)mntput(mnt); //释放相应的文件系统资源(引用计数为零时)}

原创粉丝点击