首页 | Linux 基础 | 资讯动态 | Linux 应用 | Linux 服务器 | Linux 开发 | Linux 安全 | 专题 | 联盟论坛
  当前位置:主页>Linux 开发>linux 内核>文章内容
Linux 2.6.11内核文件IO系统调用详解
来源:www.unix5.com 作者:riechelr_hl 发布时间:2007-05-20  

 

4.2.4.1.1.filp_open子函数may_open

may_open执行权限检测和文件打开,和truncate的操作。

 

 

int may_open(struct nameidata *nd, int acc_mode, int flag){
        struct dentry *dentry = nd->;dentry;
        struct inode *inode = dentry->;d_inode;
        int error;

        if (!inode) return -ENOENT; // inode为空,则返回错误

        if (S_ISLNK(inode->;i_mode)) // 连接文件,返回错误
                return -ELOOP;
        
        if (S_ISDIR(inode->;i_mode) && (flag & FMODE_WRITE))
                return -EISDIR; // 是目录且仅有写权限,返回错误

        error = permission(inode, acc_mode, nd); // 见擦inode的accmode
        if (error)
                return error;

        if (S_ISFIFO(inode->;i_mode) || S_ISSOCK(inode->;i_mode)) {
                    flag &= ~O_TRUNC; // 如果是FIFO文件,则不允许truncate
        } else if (S_ISBLK(inode->;i_mode) || S_ISCHR(inode->;i_mode)) {
                if (nd->;mnt->;mnt_flags & MNT_NODEV)
                        return -EACCES; // 如果是设备,则不允许truncate,否则返回错误
                flag &= ~O_TRUNC;
        } else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
                return -EROFS; 如果flag标识和inode权限冲突,则返回错误
        
        // 如果inode只允许append方式写入,则不允许truncate和非append写入方式。
if (IS_APPEND(inode)) {
                if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
                        return -EPERM;
                if (flag & O_TRUNC)
                        return -EPERM;
        }

        // O_NOATIME方式仅在inode用户是文件拥有者或者超级用户情况下才被允许
        if (flag & O_NOATIME)
                if (current->;fsuid != inode->;i_uid && !capable(CAP_FOWNER))
                        return -EPERM;

        // 检查是否有其他进程在使用该文件
        error = break_lease(inode, flag);
        if (error)
                return error;

        if (flag & O_TRUNC) {
                error = get_write_access(inode); // 获取一次inode写操作权限
                if (error)
                        return error;

                // 锁定inode
                error = locks_verify_locked(inode);
                if (!error) {
                        DQUOT_INIT(inode); // 对inode执行配额初始化
                        
                        error = do_truncate(dentry, 0); // truncate dentry
                }
                put_write_access(inode); // 释放当前写操作权限
                if (error)
                        return error;
        } else
                if (flag & FMODE_WRITE) // 如果有写标识,则对inode执行配额初始化
                        DQUOT_INIT(inode); 

        return 0;
}

 

4.2.4.2.open_namei子函数dentry_open

dentry_open函数主要实现文件表的对应打开等操作,返回文件指针。

 

struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags){
        struct file * f;
        struct inode *inode;
        int error;

        error = -ENFILE;
        f = get_empty_filp(); // 从进程文件表中获取一个未使用的文件结构指针,空则出错返回
        if (!f)
                goto cleanup_dentry;
        // 设置文件的flags和mode标识
        f->;f_flags = flags;
        f->;f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
        inode = dentry->;d_inode;
        if (f->;f_mode & FMODE_WRITE) {
                error = get_write_access(inode); // 获取一次inode写操作权限
                if (error)
                        goto cleanup_file;
        }
        // 初始化文件结构
        f->;f_mapping = inode->;i_mapping;
        f->;f_dentry = dentry;
        f->;f_vfsmnt = mnt;
        f->;f_pos = 0;
        f->;f_op = fops_get(inode->;i_fop);
        file_move(f, &inode->;i_sb->;s_files);

        // 调用文件驱动模块初始化物理磁盘
        if (f->;f_op && f->;f_op->;open) {
                error = f->;f_op->;open(inode,f); 
                if (error)
                        goto cleanup_all;
        }
        f->;f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

        // 初始化上次读取状态
        file_ra_state_init(&f->;f_ra, f->;f_mapping->;host->;i_mapping);

        // 如果设置了O_DIRECT,则检测文件结构中是否有驱动的操作函数指针
        if (f->;f_flags & O_DIRECT) {
                if (!f->;f_mapping->;a_ops || !f->;f_mapping->;a_ops->;direct_IO) {
                        fput(f);
                        f = ERR_PTR(-EINVAL);
                }
        }

        return f; // 返回文件结构

cleanup_all: // 出错,则释放资源并返回
        fops_put(f->;f_op);
        if (f->;f_mode & FMODE_WRITE)
                put_write_access(inode);
        file_kill(f);
        f->;f_dentry = NULL;
        f->;f_vfsmnt = NULL;
cleanup_file:
        put_filp(f);
cleanup_dentry:
        dput(dentry);
        mntput(mnt);
        return ERR_PTR(error);
}

共6页: 上一页 [1] [2] [3] 4 [5] [6] 下一页
 
如果您对本文有任何疑问或者建议,请到论坛讨论区发表您的意见: >> 论坛入口
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
  热点文章
·使用 Linux 系统调用的内核命令
·Linux操作系统的源代码目录树结
·Linux用户态与内核态的交互讲解
·Linux内核对I/O端口的管理实现(
·深入分析 Linux操作系统的内核链
·Linux内核可装载模块对设备驱动
·概述Linux系统的驱动框架及驱动
·详解Linux 2.6内核新文件系统变
·Linux系统可卸载内核模块完全指
·FreeBSD手册讲解(一)--配置FreeB
·编译Linux操作系统的内核讲解
·Linux系统可卸载内核模块完全指
  相关文章
·定制Linux内核 充分发挥系统的潜
·Linux内核模块和驱动程序的详细
·剖析Linux 2.6内核在嵌入式上的
·Linux操作系统内核启动参数详细
·详细解析Linux操作系统的内核空
·Linux内核可装载模块对设备驱动
·走向Linux系统高手之路 编译内核
·深入分析 Linux操作系统的内核链
·Linux内核入侵检测安全增强实现
·Linux内核入侵检测安全增强实现
·Linux操作系统的源代码目录树结
·使用 Linux 系统调用的内核命令

本站信息源至:互联网络,均为学习,交流所用,如有版权问题,请联系我们.
站长QQ:397422079 E_mail:riechelr_hl@unix5.com
转载本站内容请注明原作者名.谢谢!