操作系统真象还原:实现文件读写指针定位功能

14.9 实现文件读写指针定位功能

这是一个网站有所有小节的代码实现,同时也包含了Bochs等文件
实现系统调用lseek,这里是模仿的Linux下的系统调用。Iseek 原型是off_t lseek(int32_t fd, int32_t offset, uint8_t whence)fd是文件描述符, offset 是偏移量, whenceoffset 的“参照物",函数功能是设置文件读写指针fd_pos为参照物+偏移量的值,也就是说,文件指针具体的位置不仅取决于 offset,还取决于 whence。其中off_ttypedef 自定义的类型,相当于 signed int,有符号整型,因此 offset 是可正可负的值 。
whence 取值有三种取值。
SEEK_SET, offset 的参照物是文件开始处,也就是将读写位置指针设置为距文件开头偏移 offset 个字节处。
SEEK_CUR, offset 的参照物是当前读写位置,也就是将读写位置指针设置为当前位置+offset
SEEK_END, offset 的参照物是文件尺寸大小,即文件最后一个字节的下一个字节,也就是将读写位置指针设置为文件尺寸+offset

//fs.c
/*重置用于文件读写操作的偏移指针。成功时返回新的偏移量,出错时返回-1*/
int32_t sys_lseek(int32_t fd, int32_t offset, uint8_t whence){
    if(fd<0){
        printk("sys_lseek:fd error\n");
        return -1;
    }
    ASSERT(whence>0 &&whence<4);
    uint32_t _fd = fd_local2global(fd);
    struct file* pf = &file_table[_fd];
    int32_t new_pos = 0;    //新的偏移量必须位于文件大小之内
    int32_t file_size = (uint32_t)pf->fd_inode->i_size;
    switch (whence){
        /*SEEK_SET新的读写位置是相对于文件开头再增加 offset 个位移量*/
        case SEEK_SET:
            new_pos = offset;
            break;
        /*SEEK_CUR新的读写位置是相对于当前的位置增加 offset 个位移量*/
        case SEEK_CUR:
            new_pos = (int32_t)pf->fd_pos+offset;
            break;
        /*SEEK_END新的读写位置是相对于文件尺寸再增加 off set 个位移量*/  
        case SEEK_END:
            new_pos = file_size + offset;
            break;
    }
    if(new_pos<0||new_pos>(file_size-1))    return -1;

    pf->fd_pos=new_pos;
    return pf->fd_pos;
}

sys_lseek用于根据传入的参照物与偏移,重置传入的文件描述符对应的全局打开文件结构中的fd_pos。核心原理:根据传入的文件描述符,调用fd_local2global将文件描述符转换成指定的全局打开文件结构数组索引,然后switch case对传入的参照物情况进行选择,以对fd_pos做不同处理。参照物为SEET_SET,那么新的fd_pos就等于传入的偏移;参照物为SEET_CUR,那么新的fd_pos = 原来fd_pos + 传入偏移;参照物为SEET_END,那么新的fd_pos为原来文件大小 + 偏移(此时偏移量不出意外的话是负数)。

  • 15
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值