Heim  >  Artikel  >  Backend-Entwicklung  >  GOLANG: Warum funktionieren SetDeadline/SetReadDeadline/SetWriteDeadline nicht für Dateien, wenn os.File.Fd() verwendet wird?

GOLANG: Warum funktionieren SetDeadline/SetReadDeadline/SetWriteDeadline nicht für Dateien, wenn os.File.Fd() verwendet wird?

PHPz
PHPznach vorne
2024-02-09 08:30:211067Durchsuche

GOLANG:为什么在使用 os.File.Fd() 时 SetDeadline/SetReadDeadline/SetWriteDeadline 对文件不起作用?

In diesem Artikel beantwortet der PHP-Editor Zimo Ihre Frage, ob SetDeadline/SetReadDeadline/SetWriteDeadline bei Dateien nicht funktioniert, wenn os.File.Fd() in Golang verwendet wird. In Golang werden diese Methoden verwendet, um die Frist für Dateien festzulegen, aber manchmal können sie ungültig sein. Als Nächstes untersuchen wir mögliche Ursachen und bieten Lösungen an, um sicherzustellen, dass diese Methoden ordnungsgemäß funktionieren.

Frageninhalt

Ich verwende os.File.SetReadDeadlineos.File.ReadFull 的组合。但即使使用 SetReadDeadline,我设置的截止日期也被完全忽略,并且 ReadFull für immer blockieren. Warum das?

Zusätzliche Informationen: Ich feuere einige IOCTLS auf die Datei ab, daher wird os.File.Fd() benötigt, um den Dateideskriptor zu erhalten.

Lösung

tl; Arzt:

Verwenden Sie os.file.fd() 后,在文件上使用 syscall.setnonblock(fd.fd(), true)

Das liegt an read in Golang Unix:

func (fd *fd) read(p []byte) (int, error) {
    if err := fd.readlock(); err != nil {
        return 0, err
    }
    defer fd.readunlock()
    if len(p) == 0 {
        // if the caller wanted a zero byte read, return immediately
        // without trying (but after acquiring the readlock).
        // otherwise syscall.read returns 0, nil which looks like
        // io.eof.
        // todo(bradfitz): make it wait for readability? (issue 15735)
        return 0, nil
    }
    if err := fd.pd.prepareread(fd.isfile); err != nil {
        return 0, err
    }
    if fd.isstream && len(p) > maxrw {
        p = p[:maxrw]
    }
    for {
        n, err := ignoringeintrio(syscall.read, fd.sysfd, p)
        if err != nil {
            n = 0
            if err == syscall.eagain && fd.pd.pollable() {
                if err = fd.pd.waitread(fd.isfile); err == nil {
                    continue
                }
            }
        }
        err = fd.eoferror(n, err)
        return n, err
    }
}

Wenn die Datei auf den Blockierungsmodus eingestellt ist, wird das erste n, err := ignoringeintrio(syscall.read, fd.sysfd, p) 将永远阻塞。 waitread nur ausgeführt, wenn die Datei im nicht blockierenden Modus geöffnet wird. Aber ich habe die Datei im nicht blockierenden Modus geöffnet. Was ist also passiert?

Die Umsetzung von

os.file.fd() bricht es :

func (f *File) Fd() uintptr {
    if f == nil {
        return ^(uintptr(0))
    }

    // If we put the file descriptor into nonblocking mode,
    // then set it to blocking mode before we return it,
    // because historically we have always returned a descriptor
    // opened in blocking mode. The File will continue to work,
    // but any blocking operation will tie up a thread.
    if f.nonblock {
        f.pfd.SetBlocking()
    }

    return uintptr(f.pfd.Sysfd)
}

fd() Stellen Sie Dateien immer auf Blockieren ein. Daher müssen wir den Vorgang rückgängig machen, bevor wir auf das Lesen der Abfrage warten. Deshalb:

Verwenden Sie os.file.fd() 后,在文件上使用 syscall.setnonblock(fd.fd(), true)

Das obige ist der detaillierte Inhalt vonGOLANG: Warum funktionieren SetDeadline/SetReadDeadline/SetWriteDeadline nicht für Dateien, wenn os.File.Fd() verwendet wird?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen