函数解析
- os.Write函数
func (f *File) Write(b []byte) (n int, err error) {
// 判断是否f为nil
if err := f.checkValid("write"); err != nil {
return 0, err
}
// 把b写入文件
n, e := f.write(b)
if n < 0 {
n = 0
}
// 没有完成写入
if n != len(b) {
err = io.ErrShortWrite
}
// 检查e 是否是错误的管道和file.stdoutOrErr是否为真
epipecheck(f, e)
// 如果e扔不为nil则生成一个写错误
if e != nil {
err = f.wrapErr("write", e)
}
return n, err
}
主要实现是f.write()函数
↓
- f.write函数
func (f *File) write(b []byte) (n int, err error) {
// 是否file结构的pfd即文件描述符的Write方法,将b写入f, f.pfd是一个poll.FD结构体
n, err = f.pfd.Write(b)
runtime.KeepAlive(f)
return n, err
}
↓
- fd.Write函数
// Write implements io.Writer.
func (fd *FD) Write(p []byte) (int, error) {
// 获取写锁
if err := fd.writeLock(); err != nil {
return 0, err
}
defer fd.writeUnlock()
// 判断fd是否是个文件的描述符
if err := fd.pd.prepareWrite(fd.isFile); err != nil {
return 0, err
}
//
var nn int
for {
max := len(p)
if fd.IsStream && max-nn > maxRW {
max = nn + maxRW
}
n, err := ignoringEINTRIO(syscall.Write, fd.Sysfd, p[nn:max])
if n > 0 {
nn += n
}
// nn 等于len(p)写入正确
if nn == len(p) {
return nn, err
}
// 如果nn > 0 但是不等len(p)说明写入不完全意外中断
if err == syscall.EAGAIN && fd.pd.pollable() {
if err = fd.pd.waitWrite(fd.isFile); err == nil {
continue
}
}
if err != nil {
return nn, err
}
if n == 0 {
return nn, io.ErrUnexpectedEOF
}
}
}
↓
// ignoringEINTRIO is like ignoringEINTR, but just for IO calls.
func ignoringEINTRIO(fn func(fd int, p []byte) (int, error), fd int, p []byte) (int, error) {
for {
// fn : syscall.Write
n, err := fn(fd, p)
if err != syscall.EINTR {
return n, err
}
}
}
↓
- syscall.Write函数
func Write(fd int, p []byte) (n int, err error) {
if race.Enabled {
race.ReleaseMerge(unsafe.Pointer(&ioSync))
}
if faketime && (fd == 1 || fd == 2) {
n = faketimeWrite(fd, p)
if n < 0 {
n, err = 0, errnoErr(Errno(-n))
}
// 进程打开的第一个文件的fd应该默认是3
} else {
n, err = write(fd, p)
}
if race.Enabled && n > 0 {
race.ReadRange(unsafe.Pointer(&p[0]), n)
}
if msanenabled && n > 0 {
msanRead(unsafe.Pointer(&p[0]), n)
}
if asanenabled && n > 0 {
asanRead(unsafe.Pointer(&p[0]), n)
}
return
}
↓
- syscall.write函数
func write(fd int, p []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := syscall(abi.FuncPCABI0(libc_write_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
↓
- libc_unmount_trampoline函数
func libc_unmount_trampoline()
//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
根据注释说明是一个c库里的引用
↓
- glibc里的write函数定义
ssize_t
__libc_write (int fd, const void *buf, size_t nbytes)
实例
package main
import (
"fmt"
"log"
"os"
)
func main() {
file, err := os.OpenFile("./fio.conf", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatalln("OpenFile failed")
}
defer file.Close()
content := []byte("hello world")
n, err := file.Write(content)
if err != nil {
log.Fatalln("Write failed")
}
fmt.Printf("write %d bytes\n", n)
}
标签:Write,return,err,int,golang,write,fd,os
From: https://www.cnblogs.com/ishmaelwanglin/p/17058135.html