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()))

}
posted @ 2024-11-07 18:35  rincloud  阅读(64)  评论(0)    收藏  举报