Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk melaksanakan epoll di golang

Bagaimana untuk melaksanakan epoll di golang

PHPz
PHPzasal
2023-05-14 15:24:37929semak imbas

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.

  1. Prinsip asas epoll

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.

  1. epoll dalam golang

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.

  1. Pelaksanaan epollServer

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.

  1. 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
}
  1. Ringkasan

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Adakah golang chan ditutup?Artikel seterusnya:Adakah golang chan ditutup?