关于linux字符驱动中read函数filp->f_pos 和 loff_t *ppos的关系

在学习linux 字符驱动的时候会有这样的困惑

比如我们实现一个字符驱动的读函数,如下

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) {
    unsigned long p = *ppos;
    unsigned int count = size;
    int ret = 0;
    struct globalmem_dev *dev = filp->private_data;
    ...

    if (copy_to_user(buf, dev->mem +p, count)) {
        ret = -EFAULT;
    } else {
        *ppos += count;
        ret = count;
        printk(KERN_INFO "read %u byte(s) from %lu\n", count, p);
    }
    return ret;
}

为什么在成功拷贝到用户态数据之后,需要更新*ppos这个指针的数据,而不是filp->f_pos的数据

从语意上来讲应该是一致的,都是表示用户读位置的指针,为什么要费劲多传一个ppos过来,还需要内核代码对这个值去修改呢,我们自己直接修改filp中的数据不好吗?

这么做的原因是“时机”

系统要求我们更新*ppos,给系统一个机会去选择。

系统可以直接选择将ppos指向 &filp->f_pos, 也可以选择指向一个临时区域,后者拥有更大的灵活性。

比如由于某种情况不能正确返回到用户态,或者不能立即返回,这时内核临时保存这个读文件之后的偏移,filp存储的信息还是用户读之前的样子,这是符合语意的,因为用户这时确实还未读到数据,我们不能提前更新filp。

内核会在一个合适的时机将*ppos中的数据写回给filp->f_pos。

详细的讨论请参考下面的stackoverflow的链接

https://stackoverflow.com/questions/23501185/reason-why-use-loff-t-offp-instead-of-direct-filp-f-pos-usage

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值