SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin) { off_t retval; struct file * file; int fput_needed;
retval = -EBADF; file = fget_light(fd, &fput_needed); //从当前进程描述符中,获取相应file对象 if (!file) goto bad;
retval = -EINVAL; if (origin <= SEEK_MAX) { //#define SEEK_MAX SEEK_END,origin少于3. loff_t res = vfs_llseek(file, offset, origin); //调vfs层函数 retval = res; if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ } fput_light(file, fput_needed); //释放 bad: return retval; }
|
lseek系统调用,最终是由vfs_llseek实现的,看看这个函数:
loff_t vfs_llseek(struct file *file, loff_t offset, int origin) { loff_t (*fn)(struct file *, loff_t, int); //声明一fn函数.
fn = no_llseek; if (file->f_mode & FMODE_LSEEK) { fn = default_llseek; //当文件打开后,执行default_llseek函数 if (file->f_op && file->f_op->llseek) fn = file->f_op->llseek; //当前进程文件对象操作存在,执行llseek函数调用. } return fn(file, offset, origin); }
|
看看
default_llseek函数:
loff_t default_llseek(struct file *file, loff_t offset, int origin) { loff_t retval;
lock_kernel(); switch (origin) { case SEEK_END: offset += i_size_read(file->f_path.dentry->d_inode);//若标识为SEEK_END 时, 将读写指针位置指向文件尾后,并增加offset个偏移量.
break; case SEEK_CUR: if (offset == 0) { retval = file->f_pos;//若标识为SEEK_CUR,偏移量为0字节时,把当前进程文件对象位置保存. goto out; } offset += file->f_pos;//并把读写指针移动到当前位置,偏移量实际为0 } retval = -EINVAL; if (offset >= 0) { if (offset != file->f_pos) { file->f_pos = offset; //用户层传递来文件偏移量大于或小于0字节,把前进程所打开的文件对象所在当前位置移到传递来的字节数位置上。 file->f_version = 0; } retval = offset; } out: unlock_kernel(); return retval; }
|
阅读(1664) | 评论(0) | 转发(0) |