package main import ( "bytes" "fmt" "io/ioutil" "os" "golang.org/x/sys/unix" ) func main(){ var events [128] unix.EpollEvent var buf [8]byte //unix.EFD_CLOEXEC 确保在 exec 调用时关闭 efd,它可以防止文件描述符在不需要时意外地保留在新执行的程序中 //创建了一个 eventfd,它是一个特殊的文件描述符,用于在用户空间触发事件 efd,_ :=unix.Eventfd(0,unix.EFD_CLOEXEC) fmt.Printf("eventfd : %d\n", efd) //这里创建了一个 epoll 事件,关联到之前创建的 eventfd。 // unix.EPOLLHUP: // 表示挂起(Hang Up)事件。 // 对于套接字来说,这通常意味着连接已经断开(例如,对端已经关闭了连接)。 // 对于非套接字文件描述符(如 eventfd),这个标志的使用可能不太常见或没有意义。 // unix.EPOLLIN: // 表示数据可读事件。 // 当文件描述符上有数据可供读取时,会触发此事件。 // 对于 eventfd 来说,通常不需要监听 EPOLLIN,因为 eventfd 用于通知而不是数据读取。然而,如果你确实想从 eventfd 读取数据(尽管这不是典型用法),你可以监听这个事件。 // unix.EPOLLERR: // 表示错误事件。 // 当文件描述符上发生错误时,会触发此事件。 // 这可能包括各种 I/O 错误,如资源不可用、权限问题等。 event := unix.EpollEvent{ Fd: int32(efd), Events: unix.EPOLLHUP|unix.EPOLLIN|unix.EPOLLERR, } //这两行代码创建了一个 epoll 实例,并将 eventfd 添加到其中。 //当设置了EPOLL_CLOEXEC标志时,由当前进程通过fork系统调用创建的任何子进程,都会自动关闭由父进程打开的epoll实例所指向的文件描述符。这意味着子进程没有访问父进程epoll实例的权限。 epollFd,_ :=unix.EpollCreate(unix.EPOLL_CLOEXEC) //unix.EPOLL_CTL_ADD是与epoll接口相关的一个操作,用于向epoll实例中添加新的文件描述符(通常是套接字描述符)及其感兴趣的事件。 //这个操作是通过epoll_ctl函数实现的,该函数是epoll接口的核心组成部分之一。 unix.EpollCtl(epollFd,unix.EPOLL_CTL_ADD,int(efd),&event) evtFile,_:=os.Open("/sys/fs/cgroup/memory/test/memory.oom_control") data:=fmt.Sprintf("%d %d",efd, evtFile.Fd()) ioutil.WriteFile("/sys/fs/cgroup/memory/test/cgroup.event_control",[]byte(data),0700) for { n,err := unix.EpollWait(epollFd,events[:],-1) if err == nil{ for i:=0;i<n;i++{ fmt.Printf("fd %d,event:%d",events[i].Fd,events[i].Events) unix.Read(int(events[i].Fd),buf[:]) } } } unix.Close(epollFd) unix.Close(int(evtFile.Fd())) }
package main
import ( "bytes" "fmt" "io/ioutil" "os"
"golang.org/x/sys/unix" )
func main(){ var events [128] unix.EpollEvent var buf [8]byte //unix.EFD_CLOEXEC 确保在 exec 调用时关闭 efd,它可以防止文件描述符在不需要时意外地保留在新执行的程序中 //创建了一个 eventfd,它是一个特殊的文件描述符,用于在用户空间触发事件 efd,_ :=unix.Eventfd(0,unix.EFD_CLOEXEC) fmt.Printf("eventfd : %d\n", efd)
//这里创建了一个 epoll 事件,关联到之前创建的 eventfd。 // unix.EPOLLHUP: // 表示挂起(Hang Up)事件。 // 对于套接字来说,这通常意味着连接已经断开(例如,对端已经关闭了连接)。 // 对于非套接字文件描述符(如 eventfd),这个标志的使用可能不太常见或没有意义。 // unix.EPOLLIN: // 表示数据可读事件。 // 当文件描述符上有数据可供读取时,会触发此事件。 // 对于 eventfd 来说,通常不需要监听 EPOLLIN,因为 eventfd 用于通知而不是数据读取。然而,如果你确实想从 eventfd 读取数据(尽管这不是典型用法),你可以监听这个事件。 // unix.EPOLLERR: // 表示错误事件。 // 当文件描述符上发生错误时,会触发此事件。 // 这可能包括各种 I/O 错误,如资源不可用、权限问题等。 event := unix.EpollEvent{ Fd: int32(efd), Events: unix.EPOLLHUP|unix.EPOLLIN|unix.EPOLLERR, } //这两行代码创建了一个 epoll 实例,并将 eventfd 添加到其中。 //当设置了EPOLL_CLOEXEC标志时,由当前进程通过fork系统调用创建的任何子进程,都会自动关闭由父进程打开的epoll实例所指向的文件描述符。这意味着子进程没有访问父进程epoll实例的权限。 epollFd,_ :=unix.EpollCreate(unix.EPOLL_CLOEXEC) //unix.EPOLL_CTL_ADD是与epoll接口相关的一个操作,用于向epoll实例中添加新的文件描述符(通常是套接字描述符)及其感兴趣的事件。 //这个操作是通过epoll_ctl函数实现的,该函数是epoll接口的核心组成部分之一。 unix.EpollCtl(epollFd,unix.EPOLL_CTL_ADD,int(efd),&event)
evtFile,_:=os.Open("/sys/fs/cgroup/memory/test/memory.oom_control")
data:=fmt.Sprintf("%d%d",efd, evtFile.Fd()) ioutil.WriteFile("/sys/fs/cgroup/memory/test/cgroup.event_control",[]byte(data),0700)
for { n,err := unix.EpollWait(epollFd,events[:],-1) if err == nil{ for i:=0;i<n;i++{ fmt.Printf("fd %d,event:%d",events[i].Fd,events[i].Events) unix.Read(int(events[i].Fd),buf[:]) } } }
unix.Close(epollFd) unix.Close(int(evtFile.Fd()))
} 标签:epoll,oom,eventfd,描述符,golang,unix,事件,监控,efd From: https://www.cnblogs.com/rincloud/p/18533754