• system call open()


    from: http://linux2fork.blogspot.com/2013/04/system-call-open.html
     
    今天review linux character driver的時候,發現往往定義的file_operations的.open成員,參數擁有file以及inode參數,可是這個參數哪邊來的?

    其實會對open()有好奇,主要也是之前一直在trace linux kernel source內一些socket的東西,socket本身由sockfs支援,不使用open()而用socket()來開啟inode,所以想說兩者的區別是?

    kernel內用 inode 結構體用來表示data。因此,它和 file structure 用來表示一個打開了的fd並不相同。對於一個inde,可能會有多個 file structure 對應著多個已打開的多個fd,但是這都只能指向同一個 inode 結構。

    回頭看open(),大多數的system call使用interrupt 0x80,所以很快地追蹤到sys_open()是理所當然的入口

    簡化整個call stack為sys_open()=>filp_open()=>dentry_open()=>dentry_open()
    在呼叫register_chrdev()的時候將有覆寫的file_operations賦予device
    底下是一些重要的工作,完整的source code就不列了
    sys_open() : 配置fd
    filp_open() : 依賴路徑取得nameidata結構,跟著呼叫dentry_open()取回file instance
    dentry_open() : 配置file instance,nameidata結構內包含了inode instance,此時將一些必要資料由inode拷貝到file instance,f->f_op = fops_get(inode->i_fop);,此時f->f_op->open(inode,f)就是當時register_chrdev()所註冊的file_operations。
    file struct里的f_op是inode里的i_fop,文件系统的read_iter/write_iter等file_operations函数集合是先赋值给inode的i_fop成员,然后在dentry_open()里将inode.i_fop赋值给file的f_op. 如下是ext4 fs file_operations函数集赋值给inode.i_fop:
    fs/ext4/namei.c
    static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                   bool excl)
    {
        handle_t *handle;
        struct inode *inode;
        int err, credits, retries = 0;
    
        err = dquot_initialize(dir);
        if (err)
            return err;
    
        credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
               EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3);
    retry:
        inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0,
                            NULL, EXT4_HT_DIR, credits);
        handle = ext4_journal_current_handle();
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
            inode->i_op = &ext4_file_inode_operations;
            inode->i_fop = &ext4_file_operations;
            ext4_set_aops(inode);
            err = ext4_add_nondir(handle, dentry, inode);
            if (!err && IS_DIRSYNC(dir))
                ext4_handle_sync(handle);
        }
        if (handle)
            ext4_journal_stop(handle);
        if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
            goto retry;
        return err;
    }

    vfs_read

    如果file.f_op.read没有实现,实现了file.f_op.read_iter,则vfs_read会调用new_sync_read(),在这个函数里,会构建一个kiocb struct,其中的ki_pos即是ppos,即read file的offset:

    fs/read_write.c

    static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
    {
        struct iovec iov = { .iov_base = buf, .iov_len = len };
        struct kiocb kiocb;
        struct iov_iter iter;
        ssize_t ret;
    
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
        iov_iter_init(&iter, READ, &iov, 1, len);
    
        ret = call_read_iter(filp, &kiocb, &iter);
        BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
    }


    參考資料:
    http://hi.baidu.com/potyzhang/item/ae9993a919e86f17a8cfb793
    http://hi.baidu.com/heiyebujianwo/item/fa7fe543d99b73ab61d7b9cb
  • 相关阅读:
    宏的全解
    Mathematica 表达式求值
    nandflash中oob、ecc分析
    ubuntu 12.04下安装openldap,slapd.conf找不到的解决方法
    jetbrains
    看看美国公务员挣多少钱
    css的#和.的区别
    Ubuntu 14.04 LTS下安装Google Chrome浏览器
    Bootstrap 模态框(Modal)插件
    怎么旋转PDF文件的方向并保存成功
  • 原文地址:https://www.cnblogs.com/aspirs/p/14706645.html
Copyright © 2020-2023  润新知