Golang Implementing Epoll Code parsing

Source: Internet
Author: User
Tags epoll
This is a creation in Article, where the information may have evolved or changed. Before the article, I told a story, I had a friend who used to be a Java programmer, then turned around to do go, and when I asked him why he chose go, he told me that because he wrote go, no one said that he wrote the code low. It's just a joke, don't take it seriously ...
Okay, back to the chase. Golang how the network wheel is implemented, first explain what the Golang network wheel is doing, and your go program will create a m to run our system Monitoring task code as follows (all articles under the column are subject to go 1.8):
systemstack(func() {     newm(sysmon, nil)})
The Sysmon method is what we call the monitoring task, which does not bind to any P (logical processor), but rather loops through its own sleep time and time interval (the code is in Runtime/proc.go). Golang all file descriptors are set to non-blocking, a goroutine for network IO operations, read or write file descriptors, if the network IO is not ready at the moment, then this goroutine will be placed in the system waiting queue, this goroutine lost the right to run , but not really the entire system "block" in the system call, backstage and a poller will continue to poll, all the file descriptors are added to this poller, when a file descriptor is ready, The Poller will wake up the goroutine that was blocked by it, so goroutine re-run.
The Network Wheel-guide is in this for loop, getting the prepared *g (struct pointer) from the Epoll epollwait interface and finally injecting it into the available G queue under the current scheduler, with the following code:
atomic.Cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))gp := netpoll(false)if gp != nil {       injectglist(gp)}

Here Netpoll is the protagonist of today, the following is a part of the tracker code:

for {if Idle = = 0 {//20us After start sleep delay = $} else if idle > 50 {//sleep 1 milliseconds after doubling delay *= 2}if delay > 10*1000 {//10msdelay = 10 * 1000}//above is the adjustment interval usleep (delay)//sleep after several milliseconds, determine whether to schedule tracking,//and whether to do garbage collection or all P are in an idle state if Debug.schedtrace <= 0 && (sched.gcwaiting! = 0 | | atomic. Load (&sched.npidle) = = UInt32 (gomaxprocs)) {Lock (&sched.lock) if atomic. Load (&sched.gcwaiting)! = 0 | | Atomic. Load (&sched.npidle) = = UInt32 (gomaxprocs) {atomic. Store (&sched.sysmonwait, 1) Unlock (&sched.lock)//wake-up task Maxsleep: = Forcegcperiod/2if Scavengelimit < forcegcperiod {maxsleep = Scavengelimit/2}notetsleep (&sched.sysmonnote, Maxsleep) lock (&sched.lock) atomic. Store (&sched.sysmonwait, 0) noteclear (&sched.sysmonnote)//Reset Interval idle = 0delay = 20} Unlock (&sched.lock)}//distance from last pull is more than 10mslastpoll: = Int64 (atomic. LOAD64 (&sched.lastpoll)) Now: = Nanotime () Unixnow: = Unixnanotime ()//Determine when to get the last time from network I/O round finding g if lastpoll! = 0 && lastpoll+10*1000*1000 < now {//update last query G time, in order to Next time make a judgment. Atomic.                        Cas64 (&sched.lastpoll, UInt64 (Lastpoll), UInt64 (now))//This line of code is the protagonist of today, from Network I/O (I like to call network polling) Look for the Ready G, note that the GP is not blocked: = Netpoll (FALSE) if GP! = Nil {incidlelocked (-1)//found after injection into The available G-Queue injectglist (GP) incidlelocked (1) below the scheduler}}//seize p again, block system calls//seize long-running g ...}

Here's a brief description of the tracker's approximate flow, and here's our lead show time.

Using the I/O multiplexing technology, the network wheel-to-wheel-based multiplexer can handle millions of socket descriptors very efficiently, and there are Linux non-blocking IO libraries Epoll-The specific description of the column ...

I'll first list the system calls for Golang three packages

1. Create Epoll

func epollcreate(size int32) int32func epollcreate1(flags int32) int32TEXT runtime·epollcreate1(SB),NOSPLIT,$0MOVL    $329, AXMOVLflags+0(FP), BXINVOKE_SYSCALLMOVLAX, ret+4(FP)RET

Epollcreate () can create a Epoll instance. After the Linux kernel version is greater than 2.6.8, the size parameter is deprecated, but the value passed in must be greater than 0. Here's a quote on the Internet

at the initial implementation of Epollcreate (), the size parameter was used to tell the kernel how many file descriptors to use when creating an Epoll instance. The kernel uses size to request the corresponding memory (if it exceeds the given size when it is used, the kernel will request more space). Now, this size parameter is no longer used (the kernel will dynamically request the required memory). Note, however, that this size must be greater than 0, in order to be compatible with older versions of the Linux kernel code.

Epollcreate1 () If the value of flags is 0,epollcreate1 () equals to Epollcreate () except that the obsolete size is abandoned. Of course FLASG can use _epoll_cloexec = 0x80000.

2. Set Epoll Event

func epollctl(epfd, op, fd int32, ev *epollevent) int32// sys_linux_386.sTEXT runtime·epollctl(SB),NOSPLIT,$0MOVL$255, AXMOVLepfd+0(FP), BXMOVLop+4(FP), CXMOVLfd+8(FP), DXMOVLev+12(FP), SIINVOKE_SYSCALLMOVLAX, ret+16(FP)RET

The first parameter, EPFD, points to an instance of Epoll, the type of op-add event, FD is the target file descriptor to be registered, and the EV is an association-specified descriptor

The enumeration value of OP:

_EPOLL_CTL_ADD = 0x1 //在epfd中注册指定的fd文件描述符并能把event和fd关联起来。_EPOLL_CTL_MOD = 0x3 //改变 fd和evetn之间的联系。_EPOLL_CTL_DEL = 0x2 //从指定的epfd中删除fd文件描述符。在这种模式中event是被忽略的,并且为可以等于nil。

Event structure

type epollevent struct {events uint32data   [8]byte // to match amd64}

3. Wait for Epoll event

func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32TEXT runtime·epollwait(SB),NOSPLIT,$0MOVL$256, AXMOVLepfd+0(FP), BXMOVLev+4(FP), CXMOVLnev+8(FP), DXMOVLtimeout+12(FP), SIINVOKE_SYSCALLMOVLAX, ret+16(FP)RET

Epollwait This system call is used to return the ready G in the epfd . events points to the memory area of the event that the caller can use. Nev tells the kernel how many events must be greater than 0,timeout to specify a time-out.

The code implementation of the Golang network wheel-tracking device

    func netpoll (block bool) *g {if epfd = =-1 {return Nil}waitms: = Int32 ( -1) I F!block {Waitms = 0}var events [128]epolleventretry:n: = Epollwait (EPFD, &events[0], Int32 (Len (Events)), WAITMS) if n < 0 {if n! =-_eintr {println ("runtime:epollwait on FD", EPFD, "failed with",-N) throw ("Epollwait failed")}goto retry} var gp guintptrfor I: = Int32 (0); I < n; i++ {ev: = &events[i]if Ev.events = = 0 {continue}var mode int32if ev.events& (_epollin|_epollrdhup|_epollhup|_ EPOLLERR)! = 0 {mode + = ' R '}if ev.events& (_epollout|_epollhup|_epollerr)! = 0 {mode + = ' W '}if mode! = 0 {PD: = * (**pol LDESC) (unsafe. Pointer (&ev.data)) Netpollready (&GP, PD, mode)}}if block && GP = = 0 {goto Retry}return gp.ptr ()}  pre>
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.