golang oom监控实现
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()))
}

浙公网安备 33010602011771号