系统调用
系统调用在 syscall 里有一层最基础的封装:
文件 Open
func Open(path string, mode int, perm uint32) (fd int, err error)
文件 Read
func Read(fd int, p []byte) (n int, err error) func Pread(fd int, p []byte, offset int64) (n int, err error)
文件读有两个接口,一个 Read
是从 当前默认偏移 读一个 buffer 数据, Pread
接口则是从指定位置读数据的接口。
思考一个问题: Pread
从效果上来讲等于 Seek
和 Read
组合起来使用,那么是否可以认为 Pread
就可以被 Seek
+ Read
替代呢?
不行!根本原因在于 Seek
+ Read
是在用户层就是两步操作,而 Pread
虽然是 Seek
+ Read
的效果,但是操作系统给到用户的语义是: Pread
是一个原子操作。还有一个重要区别, Pread
不会改变当前文件的偏移量(普通的 Read
调用会更新偏移量)。
所以,总结下,**Pread**
和顺序调用 **Seek**
后调用 **Read**
有两点重要区别:
Pread
对用户提供的语义是原子操作,在调用Pread
时,无法中断Seek
和Read
操作;Pread
调用不会更新当前文件偏移量;
文件 Write
func Write(fd int, p []byte) (n int, err error) func Pwrite(fd int, p []byte, offset int64) (n int, err error)
文件写对应也是有两种接口, Wrtie
和 Pwrite
分别是对应 Read
和 Pread
。同样的, Pwrite
作用上也是相当于先调用 Seek
再调用 Write
,但是同样的也有 两点不同 :
Pwrite
完成Seek
和Write
对外是原子操作的语义;Pwrite
调用不会更新当前文件偏移量;
文件 Seek
func Seek(fd int, offset int64, whence int) (off int64, err error)
这个函数调用允许用户指定偏移(这个会影响到 Read
和 Write
读写的位置)。一般来说,每个打开文件都有一个相关联的“当前文件偏移量”( current file offset )。读( Read
)、写( Write
)操作都是从 当前文件偏移量处 开始,并且 Read
和 Write
会导致偏移量增加,增加量就是所读写的字节数。
小结一下 :Go 核心的 Open,Read,Write,Seek 几个系统调用,可以发现一个明显不同与标准 IO 库的区别: 系统调用操作对象是一个整数句柄 。 Open
文件得到一个整数 fd,之后的所有 IO 都是针对这个 fd 来操作的。这个明显和标准库不同,os 标准库 OpenFile 得到的是一个 File
结构体,所有的 IO 也是针对这个结构体的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论