IO 多路复用之 epoll 问题记录
记录使用 epoll 时的一些疑惑和问题
一、epoll 可以监听普通文件吗
先以一段代码来验证
1 |
|
运行后结果如下:
记录使用 epoll 时的一些疑惑和问题
先以一段代码来验证
1 |
|
运行后结果如下:
我的环境,物理机是 Inter x86_86 机器,装的是 window 10 操作系统。使用软件 VMware 虚拟化出来一个 ubuntu 18.04 的虚拟机。然后在此虚拟机上进行实验。
我们一个操作系统需要在硬件跑起来,也就是进行开机操作,需要进行如下的步骤:
PC 硬件主机加电 –> PC 机 BIOS 固件 –> 加载可引导设备中的 GRUB –> GRUB 引导 –> 加载硬件分区中的 OS 文件 –> OS
PC 机 BIOS 固件是固化在 PC 机主板上的 ROM 芯片中的,掉电也能保存,PC 机上电的第一条指令就是 BIOS 固件中的,他负责检测和初始化 CPU、内存以及主板平台,然后加载引导设备(大概率是硬件)中的第一个扇区数据,到 0x7c00 地址开始的内存空间,再跳转到 0x7c00 处执行指令,也就是 GRUB 引导程序。
GRUB 引导程序我们暂不深究,如果下载了 ubuntu linux 操作系统,GRUB 就已经存在了。我们先来直接使用。本次我们直接从 OS 这一步入手。
eBPF 全称是“扩展的伯克利数据包过滤器”(Extended Berkeley Packet Filter
),是一种数据包过滤技术,是从 BPF 技术扩展而来。BPF 提供了一种在内核事件和用户程序事件发生时安全注入代码的机制,这就让非内核开发人员也可以对内核进行控制。随着内核的发展,BPF 逐步从最初的数据包过滤扩展到了网络、内核、安全、跟踪等,而且它的功能特性还在快速发展中,这种扩展后的 BPF 被简称为 eBPF。
在 eBPF 之前,内核模块是注入内核的最主要机制。由于缺乏对内核模块的安全控制,内核的基本功能很容易被一个有缺陷的内核模块破坏。而 eBPF 则借助即时编译器(JIT),在内核中运行了一个虚拟机,保证只有被验证安全的 eBPF 指令才会被内核执行。同时,因为 eBPF 指令依然运行在内核中,无需向用户态复制数据,这就大大提高了事件处理的效率。
正是由于这些突出的特性,eBPF 现如今已经在故障诊断、网络优化、安全控制、性能监控等领域获得大量应用。比如,Facebook 开源的高性能网络负载均衡器 Katran、Isovalent 开源的容器网络方案 Cilium ,以及著名的内核跟踪排错工具 BCC 和 bpftrace 等,都是基于 eBPF 技术实现的。
我们在开发新的 eBPF 程序时,内核社区提供的 libbpf 库(https://github.com/libbpf/libbpf)不仅可以帮我们避免直接调用内核函数,而且还提供了跨内核版本的兼容性(即一次编译到处执行,简称 CO-RE
)
eBPF 需要事件触发后才会执行,这些事件包括系统调用、内核跟踪点、内核函数和用户态函数的调用退出、网络事件等。借助于强大的内核态插桩和用户态插桩,eBPF 程序几乎可以在内核和应用的任意位置进行插桩。
bbc 使用 ebpf 提供了一个叫做memleak
的工具,是专门用来检测内存泄露的。它可以跟踪系统或者指定进程的内存分配、释放请求,然后定期输出一个未释放内存和相应调⽤栈的汇总情况(默认5 秒)。
代码地址:https://github.com/iovisor/bcc/blob/master/tools/memleak.py
注意,这个工具会定期输出未释放的内存以及相应调用栈的汇总情况。所以如下情况也会被检测出来。
1 | void test3() { |