(2.2)file_operation 实现具体操作:思考一

【思考一:内核是如何将app里的操作函数和驱动里的操作函数联系上的呢?】

 参考: Linux 内核sys_open文件系统与设备操作流程分析
            走马观花:Linux 系统调用 open 七日游 

       一般用户在应用程序里调用的 open, read, write 函数是 c 库的函数,这些函数会触发 swi val异常,从而引发系统调用,进入到内核空间,内核通过VFS(virtual Filesystem)来实现调用不同的驱动函数。

(2.2)file_operation 实现具体操作:思考一_第1张图片

例一:open:使用地址的字符串如‘’/dev/led‘’,找到文件系统中的设备节点,再调用对应的open函数

open –> sys.open –> leddrv.open

fs/open.c

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
    if (force_o_largefile())
        flags |= O_LARGEFILE;

    return do_sys_open(AT_FDCWD, filename, flags, mode);
}

其中SYSCALL_DEFINE3是在include/linux/syscalls.h中定义的宏定义

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

#define SYSCALL_DEFINEx(x, sname, ...) \
    SYSCALL_METADATA(sname, x, __VA_ARGS__) \
    __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

定义名中的数字3,表示你在调用函数书传入的参数个数,当在应用程序中传入几个参数,就调用对应的SYSCALL_DEFINE*(name, ...),name表示是那种系统调用,比如这里是open,对应的就是open,的系统调用。

下一步就是调用了 do_sys_open()这个函数,执行真正的系统open命令

太复杂了。。。涉及的东西太多,只写一个顺利的完整流程吧

do_sys_open
    |
    do_filp_open
        |
        path_openat
            /* 关键的字符串解析处理函数,其核心思想是分级解析字符串, 通过字符串对应的目录项找到下一级目录的inode节点。 */
            link_path_walk
            /* do_last函数创建或者获取文件对应的inode对象,并且初始化file对象, 至此一个表示打开文件的内存对象filp诞生 */
            do_last
                |
                //finish_open_created:
                vfs_open
                    |
                    do_dentry_open
                        |
                        f->f_op = fops_get(inode->i_fop); /* 获得file_operation结构体 */
                        if (!open)
                            open = f->f_op->open;
                        if (open) { /* 调用真正的open函数 */
                            error = open(inode, f);
                            if (error)
                                goto cleanup_all;
                        }

例二:write:通过open得到的文件描述符fd,调用对应的drv_write

fs/read_write.c

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,size_t, count)
    |
    struct fd f = fdget_pos(fd); /* 根据fd得到对应的文件 */
    vfs_write(f.file, buf, count, &pos);
        |
         __vfs_write(file, buf, count, pos);
            |
            file->f_op->write(file, p, count, pos); /* 调用对应的write函数 */

 

你可能感兴趣的:(cdev总结2018)