字符设备驱动offset疑问:echo写入时为何offset值为0?
关于字符设备驱动中
offset的疑问解答 首先先提个小细节:你的write函数里写了printk(KERN_INFO "read\n");,这明显是个笔误吧?毕竟执行echo是写入操作,会进入write函数,所以你才会看到输出里有"read",先纠正这个小问题~
为什么执行echo "hi" > /dev/device_name时offset是0?
当你用echo "hi" > /dev/device_name时,shell会以O_WRONLY | O_TRUNC的标志打开你的设备文件:
O_TRUNC标志会把设备文件的长度截断为0,同时内核会将这个文件描述符对应的当前读写偏移量(也就是驱动函数里的offset参数)初始化为0。- 而且
echo是一次性把所有数据写入设备,整个过程没有调用lseek来修改偏移量,所以当驱动的write函数被调用时,传入的offset就是初始的0。
offset到底有什么作用?
offset是内核为每个打开的文件描述符维护的当前读写位置指针,它的核心作用是让驱动支持随机访问或者顺序追加读写,具体来说:
- 对于串口、键盘这种流式字符设备,它们本身不支持随机访问,驱动通常会忽略
offset参数——毕竟数据是流式的,没有固定的位置可言。 - 但对于你这种模拟内存缓冲区的字符设备(用
ker_buff作为内核缓冲区),offset就非常关键:simple_read_from_buffer和simple_write_to_buffer这两个内核函数就是基于offset来操作缓冲区的:写入时从ker_buff + offset的位置开始写,读取时从ker_buff + offset的位置开始读。- 每次读写操作完成后,内核会自动更新
offset的值(比如写入了2个字节,offset就会增加2),这样下次再调用read/write时,就会从新的位置开始操作,实现顺序读写。 - 如果用户调用了
lseek系统调用(比如dd seek=5 of=/dev/device_name),内核会修改这个offset的值,驱动的read/write函数就会使用新的偏移量来操作缓冲区,实现随机访问。
举个实际例子:如果你执行echo "hello" > /dev/device_name,此时offset会被更新为5(假设写入了5个字符);接着执行echo "world" >> /dev/device_name,>>会让shell以O_APPEND标志打开文件,内核会自动把offset设置为当前文件的长度(也就是5),这时write函数的offset就是5,写入的"world"会追加到内核缓冲区的第5个位置之后。
内容的提问来源于stack exchange,提问作者Rabiraj
相关产品推荐
相关产品推荐

