STEP1: user space===>read man 2 n = read(fd[0], line, MAXLINE); STEP2: kernel===>sys_read unistd.h /* fs/pipe.c */ #define __NR_pipe2 59 __SYSCALL(__NR_pipe2, sys_pipe2) /* fs/quota.c */ #define __NR_quotactl 60 __SYSCALL(__NR_quotactl, sys_quotactl) /* fs/readdir.c */ #define __NR_getdents64 61 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64 __SC_COMP(__NR_getdents64, sys_getdents64, compat_sys_getdents64) /* fs/read_write.c */ #define __NR3264_lseek 62 __SC_3264(__NR3264_lseek, sys_llseek, sys_lseek) #define __NR_read 63 __SYSCALL(__NR_read, sys_read) #define __NR_write 64 __SYSCALL(__NR_write, sys_write) STEP3: read_write.c SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)//argv:fd, buf, count { struct fd f = fdget_pos(fd);//fd-->f ssize_t ret = -EBADF; if (f.file) { loff_t pos = file_pos_read(f.file);//pos出世,拿到此文件当前的pos ret = vfs_read(f.file, buf, count, &pos);//调用到 vfs_read(), argv:f.file, buf, cout, pos if (ret >= 0) file_pos_write(f.file, pos);//一旦vfs_read成功返回,我需要修改f.file中pos的位置,这样内核就一直记录着每个文件的pos fdput_pos(f); } return ret; } STEP4: read-->vfs_read(f.file, buf, count, &pos); 这里还没有调用到我们对应设备的fops ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { ssize_t ret; if (!(file->f_mode & FMODE_READ)) return -EBADF; if (!(file->f_mode & FMODE_CAN_READ)) return -EINVAL; if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT; ret = rw_verify_area(READ, file, pos, count); if (ret >= 0) { count = ret; if (file->f_op->read) ret = file->f_op->read(file, buf, count, pos);//调用到file->f_op->read注意参数. else if (file->f_op->aio_read) ret = do_sync_read(file, buf, count, pos); else ret = new_sync_read(file, buf, count, pos); if (ret > 0) { fsnotify_access(file); add_rchar(current, ret); } inc_syscr(current); } return ret; } STEP5: 使用读管道的例子. n = read(fd[0], line, MAXLINE); const struct file_operations pipefifo_fops = { .open = fifo_open, .llseek = no_llseek, .read = new_sync_read,//会调用到设备的read .read_iter = pipe_read, .write = new_sync_write, .write_iter = pipe_write, .poll = pipe_poll, .unlocked_ioctl = pipe_ioctl, .release = pipe_release, .fasync = pipe_fasync, }; 调用方STEP4: ret = file->f_op->read(file, buf, count, pos);//调用到file->f_op->read注意参数. 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; kiocb.ki_nbytes = len; iov_iter_init(&iter, READ, &iov, 1, len); ret = filp->f_op->read_iter(&kiocb, &iter);//注意参数改变. if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); *ppos = kiocb.ki_pos; return ret; } STEP6:new_sync_read调用方 ret = filp->f_op->read_iter(&kiocb, &iter);//注意参数改变. pipe_read(struct kiocb *iocb, struct iov_iter *to);参数在调用方函数中. STEP: END 回顾调用流程 1.read(fd[0], line, MAXLINE); 2.SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) 3.在2中被调用vfs_read(f.file, buf, count, &pos) ---> 可以参看vfs_open 中会回调open会调用到设备的open,完成filpe和inode的关联 4.在3中被调用ret = file->f_op->read(file, buf, count, pos); 5.对应于4,new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 6.在5中被调用ret = filp->f_op->read_iter(&kiocb, &iter) 7.对应于6,pipe_read(struct kiocb *iocb, struct iov_iter *to)