General IO model of [golang system programming]

Time:2020-1-2

All system calls that perform I / O operations use a non negative integer (file descriptor) to describe open files (files, pipes, sockets, terminals, devices).

Three common file descriptors:
File descriptor purpose POSIX name Stdio flow
0 Standard input STDIN_FILENO stdin
1 standard output STDOUT_FILENO stdout
2 Standard error STDERR_FILENO stderr
Four system calls of general IO model
The following four system calls are in the form of C
  • FD = open (pathname, flags, mode): pathname is the name of the open file, flags specifies the opening method of the file, mode specifies the access permission of the file, and the returned FD is the file descriptor mentioned above
  • Num = read (FD, buffer, count): read up to n bytes of data from the buffer
  • Num = write (FD, buffer, count): write up to n bytes of data from the buffer, and return num may be less than count
  • status = close(fd)
In golang, we can also use system calls through the standard library syscall package
  • 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)

It can be seen that the system call of golang has no count parameter, and the default buffer size is the length of count.

The following is a piece of code for copying files without checking all errors

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

    //Here, some flags are used to specify the opening method of the file. Mode specifies the access permission of the file. Next, continue
    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])

    }
}
System call details
open()

The open function returns the following errors:

  • Syscall.eacces: the file permission does not allow the file to be opened with the specified flags parameter. Possible reasons include directory permission restriction, file does not exist and cannot be created
  • Syacall.eisdir: the caller attempted to open a directory to write to the file
  • Syscall.emfile: the number of file descriptors opened by the process has reached the maximum process resource limit
  • Syscall.enfile: the number of files opened has reached the maximum allowed by the system (emfile is the maximum number of processes)
  • Syscall.enoent: the file or path does not exist, and the o’creat flag is not specified (this error is common)
  • Syscall.erofs: an attempt was made to open a read-only file in write mode
  • Syscall.etxtbsy: Specifies that the file is executable and running,The system does not allow running programs

There is a create system call in the system call, but in golang, thisfunc Creat(path string, mode uint32) (fd int, err error)It is implemented using the system call open().

read()

If the read call succeeds, the number of bytes actually read will be returned,0 if end of file (EOF)

write()

num, err := syscall.Write(fd, buff), Num is the number of writes, generally equal to len (buff), whennum<len(buff), which is called “partial write”. It may be due to insufficient disk. The success of write call does not mean the success of data writing.

Lseek(): change the offset of the file

The operating system saves the offset of the open file (also known as the read-write offset or pointer). For documents only.

Lssek in golangfunc Seek(fd int, offset int64, whence int) (off int64, err error)

FD: file descriptor
Offset: file offset
When: what base point to interpret the offset parameter

whence

  • Set: io.seekstart, offset bytes from the file header
  • Seek? Cur: io.seekcurrent, offset bytes from the current file offset
  • Seek end: io.seek end, offset bytes from the end of the file

Document void

Scene: when the offset of the file exceeds the end of the file

  • Read: returns 0 to read to the end of the file
  • Write: data can be written anywhere at the end of the file

The space from the end of the file to the beginning of the newly written data is calledDocument void

The file hole does not occupy any disk space. Until it lasts for a certain point, the disk will allocate the disk block when the data system is written in the file hole. The advantage of file hole is that compared with the actual empty byte allocation disk, the sparse filled file takes up less disk space. Systems that do not support empty files write empty bytes to files.The presence of file holes means that the nominal size is larger than the total amount of disk storage consumed