go语言通用的IO模型-4个基本系统调用

所有执行I/O操作的系统调用,都使用一个非负整数(文件描述符)来描述打开的文件(文件、管道、socket、终端、设备)。

常见的3种文件描述符:

文件描述符 用途 POSIX名称 stdio流
0 标准输入 STDIN_FILENO stdin
1 标准输出 STDOUT_FILENO stdout
2 标准错误 STDERR_FILENO stderr

通用IO模型的4个系统调用

下面的四个系统调用为c语言的形式

  • fd = open(pathname, flags, mode):pathname是打开的文件名,flags指定文件的打开方式,mode指定文件的访问权限,返回的fd为上文所说的文件描述符
  • num = read(fd, buffer, count):从buffer中读取至多n个字节的数据
  • num = write(fd, buffer, count):从buffer中写入至多n个字节的数据,返回num可能小于count(不清楚什么情况)
  • status = close(fd)

在golang中,我们也可以通过标准库syscall包使用系统调用

  • func Open(path string, mode int, perm uint32) (fd int, err error)
  • func Read(fd int, p []byte) (n int, err error)
  • func Write(fd int, p []byte) (n int, err error)
  • func Close(fd int) (err error)

可见golang的系统调用没有count参数,默认Buffer的大小为count的长度。
下面是一段代码,用来进行文件的复制,没有检查全部的error

func Copy(oldFile, newFile string) {
    inputFd, err := syscall.Open(oldFile, os.O_RDONLY, 0666)
    if err != nil {
        panic(err)
    }

    // 此处用到了部分flags指定文件的打开方式,mode指定文件的访问权限下一篇继续
    outputFd, err := syscall.Open(newFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0666)
    if err != nil {
        panic(err)
    }

    defer syscall.Close(inputFd)
    defer syscall.Close(outputFd)

    buff := make([]byte, 10)
    for {
        size, _ := syscall.Read(inputFd, buff)
        if size == 0 {
            break
        }
    
        syscall.Write(outputFd, buff[:size])

    }
}