Rumah > Artikel > pembangunan bahagian belakang > os.OpenFile dengan O_RDONLY tergantung pada paip bernama tanpa penulis
PHP Editor Banana memperkenalkan anda kepada kaedah operasi khas, iaitu menggunakan fungsi os.OpenFile dengan O_RDONLY untuk melekapkan pada paip bernama tanpa penulis. Kaedah operasi ini boleh merealisasikan operasi membaca paip bernama, membolehkan anda mendapatkan maklumat data dengan mudah dalam paip bernama tanpa menggunakan penulis. Teknik ini mudah difahami dan mudah dikendalikan, menjadikannya pilihan yang sangat baik untuk pembangun apabila berurusan dengan paip bernama. Seterusnya, kami akan memperkenalkan anda secara terperinci cara menggunakan kaedah ini untuk melaksanakan operasi membaca paip yang dinamakan.
Saya sedang menulis daemon yang sepatutnya menerima pemberitahuan daripada arahan ad-hoc cli dan memilih untuk berbuat demikian melalui paip bernama unix. Saya menulis pakej pendek yang pada satu tangan menghasilkan goroutine yang berasingan untuk dibaca daripada nod dan menghantar pemberitahuan yang diterima ke saluran (taman permainan dengan ujian unit):
type Writer struct { f *os.File } func NewWriter(ipc string) (*Writer, error) { f, err := os.OpenFile(ipc, os.O_WRONLY, 0600) if err != nil { return nil, fmt.Errorf("writer: open file: %w", err) } return &Writer{f: f}, nil } func (w *Writer) WriteString(str string) (int, error) { return w.f.WriteString(fmt.Sprint(str, "\n")) } func (w *Writer) Close() error { return w.f.Close() } type Reader struct { f *os.File rmFn func() error quit chan struct{} done *sync.WaitGroup } func NewReader(ipc string) (*Reader, error) { err := syscall.Mkfifo(ipc, 0640) if err != nil { return nil, fmt.Errorf("reader: create fifo: %w", err) } f, err := os.OpenFile(ipc, os.O_RDONLY, 0640) if err != nil { return nil, fmt.Errorf("reader: open fifo: %w", err) } return &Reader{ f: f, quit: make(chan struct{}), done: &sync.WaitGroup{}, rmFn: func() error { return os.Remove(ipc) }, }, nil } func (r *Reader) PollRead() <-chan string { reader := bufio.NewReader(r.f) out := make(chan string) r.done.Add(1) go func() { defer r.done.Done() for { line, err := reader.ReadBytes('\n') if err != nil { fmt.Printf("error reading from named pipe: %v\n", err) return } nline := string(line) nline = strings.TrimRight(nline, "\n") select { case out <- nline: case <-r.quit: close(out) return } } }() return out } func (r *Reader) Close() error { close(r.quit) r.done.Wait() err := r.f.Close() if err != nil { return fmt.Errorf("error closing named pipe: %v", err) } err = r.rmFn() if err != nil { return fmt.Errorf("error removing named pipe: %v", err) } return nil }
Ini nampaknya berkesan, tetapi ia mengalami tingkah laku yang pelik di mana tiada pembaca boleh membuka fail sebelum mana-mana penulis membuka fail, yang nampaknya berlaku berdasarkan catatan lain yang saya baca mengenai kandungan subjek untuk membalikkan tingkah laku; aduan yang biasa ialah penulis menggantung kerana tidak ada pembaca, bagaimanapun, di sini pembaca tidak boleh dibuat seketika.
Ini ialah antara muka sistem posix中记录的默认行为>:
o_nonblock Apabila membuka fifo dengan set o_rdonly atau o_wronly: jika o_nonblock ditetapkan, baca sahaja open() akan kembali tanpa kelewatan. Jika tiada proses, write-only open() akan mengembalikan ralat Fail sedang dibuka untuk dibaca.
Jika o_nonblock dikosongkan, read-only open() akan menyekat Dipanggil sehingga utas membuka fail untuk menulis. terbuka() Tulis sahaja harus menyekat utas panggilan sehingga utas dibuka Fail untuk bacaan.
Apabila membuka fail khas blok atau aksara khas yang disokong Terbuka tanpa sekatan:
Jika o_nonblock ditetapkan, fungsi open() akan kembali tanpa Elakkan peranti daripada sedia atau tersedia. tingkah laku seterusnya Sifat peranti adalah khusus peranti.
Jika o_nonblock dikosongkan, fungsi open() akan menyekat panggilan l> Benang tidak kembali sehingga peranti sedia atau tersedia.
Jika tidak, bendera o_nonblock tidak menyebabkan ralat, tetapi ia berlaku Ia tidak dinyatakan sama ada bendera status fail mengandungi o_nonblock logo.
Jadi penyelesaiannya adalah dengan meletakkan syscall.o_nonblock
标志添加到 openfile
dalam panggilan:
f, err := os.OpenFile(ipc, os.O_RDONLY|syscall.O_NONBLOCK, 0640)
EDIT: Seperti yang dibincangkan dalam ulasan, penyelesaian ini tidak mudah alih untuk darwin
环境。更便携的解决方案是在读取器端使用 o_rdwr
membuka fail.
Atas ialah kandungan terperinci os.OpenFile dengan O_RDONLY tergantung pada paip bernama tanpa penulis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!