Dalam sistem pengendalian Linux, epoll ialah mekanisme pemberitahuan acara I/O yang sangat cekap. Apabila menggunakan epoll, anda boleh mengikat berbilang deskriptor fail kepada satu epoll contoh epoll akan memberitahu program tentang peristiwa I/O yang berlaku pada semua deskriptor fail. Berbanding dengan mekanisme pemberitahuan acara I/O lain seperti pilih dan tinjauan pendapat, epoll mempunyai kecekapan yang lebih tinggi dan overhed yang lebih rendah. Dalam artikel ini, kami akan memperkenalkan cara melaksanakan epoll dalam golang.
Dalam Linux, setiap proses mempunyai jadual deskriptor fail sendiri Apabila proses perlu melaksanakan operasi I/O, ia perlu lulus Fail deskriptor untuk mengakses fail atau soket yang sepadan. Apabila fail atau soket sedia, kernel akan memberitahu proses ini adalah peristiwa I/O. Apabila peristiwa I/O berlaku, pilih dan tinjauan pendapat akan merentasi semua set deskriptor fail, tetapi epoll berbeza hanya akan merentasi set deskriptor fail di mana peristiwa I/O berlaku.
epoll pada asasnya terdiri daripada tiga panggilan sistem: epoll_create, epoll_ctl dan epoll_wait. epoll_create digunakan untuk mencipta contoh epoll, epoll_ctl digunakan untuk menambah/memadam/mengubah suai deskriptor fail pada contoh epoll, dan epoll_wait digunakan untuk menunggu peristiwa berlaku pada deskriptor fail.
Dalam golang, epoll dilaksanakan oleh pakej net/netutil. Ia dikapsulkan berdasarkan panggilan sistem epoll_create, epoll_ctl dan epoll_wait. golang merangkum epoll ke dalam fail dalaman/poll/epoll netutil.
Apabila golang melaksanakan epoll, ia mentakrifkan jenis contoh epoll masing-masing epollServer dan epollDesc. Antaranya, epollServer mengandungi contoh epoll, yang digunakan untuk menyimpan deskriptor fail dan peristiwa I/O digunakan untuk mewakili deskriptor fail dan peristiwa I/O yang berkaitan.
Mari kita lihat pelaksanaan epollServer terlebih dahulu. epollServer mengandungi medan berikut:
type epollServer struct { // events 是一个数组,用于存储返回的 I/O 事件 events []syscall.EpollEvent // epollFd 是 epoll 实例的文件描述符 epollFd int // fds 用于存储文件描述符和对应的 epollDesc fds map[int]*epollDesc }
Pertama, untuk mencipta contoh epollServer, anda perlu memanggil fungsi newEpollServer yang disediakan oleh golang.
func newEpollServer() (ep *epollServer, err error) { // 创建 epoll 实例 ep = &epollServer{ events: make([]syscall.EpollEvent, epollServerBlock), fds: make(map[int]*epollDesc), } ep.epollFd, err = syscall.EpollCreate1(0) if err != nil { return nil, err } // 将 epoll 实例添加到 epollServer 的文件描述符映射表中 ep.fds[ep.epollFd] = &epollDesc{ep, syscall.EPOLLIN} return ep, nil }
Kita dapat melihat bahawa apabila membuat tika epollServer, tika epoll akan dibuat terlebih dahulu melalui panggilan syscall.EpollCreate1(0), dan kemudian ditambahkan pada jadual pemetaan deskriptor fail epollServer.
Kemudian, kita boleh menambah deskriptor fail pada contoh epollServer melalui kaedah addFD.
func (ep *epollServer) addFD(fd int, mode int) error { // 设置文件描述符的非阻塞模式 if err := syscall.SetNonblock(fd, true); err != nil { return err } // 将文件描述符的 I/O 事件添加到 epoll 实例中 ev := syscall.EpollEvent{Fd: int32(fd), Events: syscall.EPOLLIN | syscall.EPOLLOUT} if err := syscall.EpollCtl(ep.epollFd, syscall.EPOLL_CTL_ADD, fd, &ev); err != nil { return err } // 将文件描述符和 epollDesc 添加到文件描述符映射表中 ep.fds[fd] = &epollDesc{ep, mode} return nil }
Dalam kaedah addFD, mula-mula tetapkan deskriptor fail kepada mod tidak menyekat, dan kemudian tambahkan peristiwa I/O deskriptor fail pada contoh epoll. Akhir sekali, tambahkan deskriptor fail dan epollDesc yang sepadan pada jadual pemetaan deskriptor fail.
Akhir sekali, kita boleh menunggu peristiwa I/O yang berlaku pada deskriptor fail melalui kaedah tunggu.
func (ep *epollServer) wait(ms int) ([]syscall.EpollEvent, error) { if ms < 0 { ms = -1 } // 等待发生 I/O 事件 nEvents, err := syscall.EpollWait(ep.epollFd, ep.events, ms) if err != nil { return nil, err } // 返回发生的 I/O 事件 return ep.events[:nEvents], nil }
Kini, kami telah memahami bagaimana epollServer dilaksanakan di golang. Seterusnya kami akan memperkenalkan kaedah pelaksanaan epollDesc.
epollDesc digunakan untuk mewakili deskriptor fail dan peristiwa I/O yang sepadan. Pelaksanaannya sangat mudah, hanya memerlukan penunjuk ke epollServer dan integer yang mewakili acara I/O.
type epollDesc struct { srv *epollServer mode int }
Dalam artikel ini, kami memperkenalkan cara menggunakan epoll dalam golang untuk melaksanakan mekanisme pemberitahuan acara I/O yang cekap. Kami memperkenalkan secara terperinci prinsip asas pelaksanaan epoll dan golang bagi epollServer dan epollDesc. Saya percaya bahawa dengan membaca artikel ini, anda boleh lebih memahami pelaksanaan epoll dalam golang dan memberikan rujukan untuk memilih mekanisme pemberitahuan acara I/O yang sesuai untuk projek anda.
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan epoll di golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!