Maison  >  Article  >  développement back-end  >  GOLANG : Pourquoi SetDeadline/SetReadDeadline/SetWriteDeadline ne fonctionne-t-il pas pour les fichiers lors de l'utilisation de os.File.Fd() ?

GOLANG : Pourquoi SetDeadline/SetReadDeadline/SetWriteDeadline ne fonctionne-t-il pas pour les fichiers lors de l'utilisation de os.File.Fd() ?

PHPz
PHPzavant
2024-02-09 08:30:211067parcourir

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

Dans cet article, l'éditeur PHP Zimo répondra à votre question sur SetDeadline/SetReadDeadline/SetWriteDeadline qui ne fonctionne pas sur les fichiers lors de l'utilisation de os.File.Fd() dans Golang. Dans Golang, ces méthodes sont utilisées pour fixer la date limite des fichiers, mais elles peuvent parfois être invalides. Nous explorerons ensuite les causes possibles et proposerons des solutions pour garantir le bon fonctionnement de ces méthodes.

Contenu des questions

J'utilise os.File.SetReadDeadlineos.File.ReadFull 的组合。但即使使用 SetReadDeadline,我设置的截止日期也被完全忽略,并且 ReadFull le blocage permanent. pourquoi donc?

Informations supplémentaires : je lance des IOCTLS sur le fichier, donc os.File.Fd() est nécessaire pour obtenir le descripteur de fichier.

Solution

tl; Docteur :

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

Cela est dû à read dans 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
    }
}

Si le fichier est défini en mode bloquant, le premier n, err := ignoringeintrio(syscall.read, fd.sysfd, p) 将永远阻塞。 waitread ne sera exécuté que si le fichier est ouvert en mode non bloquant. Mais j’ai ouvert le fichier en mode non bloquant, alors que s’est-il passé ?

La mise en œuvre de

os.file.fd() le casse  :

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() Définissez toujours les fichiers sur blocage. Par conséquent, nous devons annuler l’opération avant d’attendre la lecture du sondage. Donc :

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer