STEP1:open int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); STEP2:实现open(pathname, flags, mod) 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); } STEP3: do_sys_open(AT_FDCWD, filename, flags, mode); filename : const char *pathname flags: flags mode : mode add: AT_FDCWD #define AT_FDCWD -100 /* Special value used to indicate openat should use the current working directory. */ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) { struct open_flags op; int fd = build_open_flags(flags, mode, &op);//mode-->op struct filename *tmp; if (fd) return fd; tmp = getname(filename);//path(filename)--->filename if (IS_ERR(tmp)) return PTR_ERR(tmp); fd = get_unused_fd_flags(flags);//分配一个可用的fd if (fd >= 0) { struct file *f = do_filp_open(dfd, tmp, &op);//dfd,tmp,op==>分配file if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); } else { fsnotify_open(f);//f关联到inode. fd_install(fd, f);//补冲说明fd和file的关系. } } putname(tmp); return fd; } add: fd_install(fd, f) -->__fd_install(current->files, fd, file); /* * Install a file pointer in the fd array. * * The VFS is full of places where we drop the files lock between * setting the open_fds bitmap and installing the file in the file * array. At any such point, we are vulnerable to a dup2() race * installing a file in the array before us. We need to detect this and * fput() the struct file we are about to overwrite in this case. * * It should never happen - if we allow dup2() do it, _really_ bad things * will follow. * * NOTE: __fd_install() variant is really, really low-level; don't * use it unless you are forced to by truly lousy API shoved down * your throat. 'files' *MUST* be either current->files or obtained * by get_files_struct(current) done by whoever had given it to you, * or really bad things will happen. Normally you want to use * fd_install() instead. */ __fd_install(current->files, fd, file); void __fd_install(struct files_struct *files, unsigned int fd, struct file *file) { struct fdtable *fdt; spin_lock(&files->file_lock); fdt = files_fdtable(files); BUG_ON(fdt->fd[fd] != NULL); rcu_assign_pointer(fdt->fd[fd], file);//file关联到fd spin_unlock(&files->file_lock); } STEP4: open(); do_sys_open(AT_FDCWD, filename, flags, mode); do_filp_open(dfd, tmp, &op); -->path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); -->error = do_last(nd, &path, file, op, &opened, pathname); -->error = vfs_open(&nd->path, file, current_cred()); -->do_dentry_open(filp, NULL, cred); 注意第二个参数 STEP5: 如何调用到底层的dev->open static int do_dentry_open(struct file *f, int (*open)(struct inode *, struct file *),//会回调设备的open const struct cred *cred) { if (!open) open = f->f_op->open;//设备对应的open if (open) { error = open(inode, f);//对应我们写驱动时, ............. } 我们使用char.c中的chardev_open,查看其参数.现在真相已经很显然,只要我们 f->f_op->open = char_open 就会调用. static int chrdev_open(struct inode *inode, struct file *filp) 1.设备初始化时,就会绑定fops cdev->ops = fops; 2.初始化fops const struct file_operations def_chr_fops = { .open = chrdev_open,//因此系统调用open就会一直调用到底层的chrdev_open. .llseek = noop_llseek, }; STEP:END 1.int open(const char *pathname, int flags, mode_t mode); 2.SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) 3.do_sys_open(AT_FDCWD, filename, flags, mode); 4. do_sys_open(AT_FDCWD, filename, flags, mode); do_filp_open(dfd, tmp, &op); -->path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); -->error = do_last(nd, &path, file, op, &opened, pathname); -->error = vfs_open(&nd->path, file, current_cred()); -->do_dentry_open(filp, NULL, cred); 注意第二个参数 调用设备的open;