[1]王小强. MEMDOG:一种基于Linux的在线内存检测器[D].兰州大学,2017.
由于 DRAM 的容量不断地增大,体积不断地减小,因此表示一个位信息的存储单元在不断地缩小,使得 DRAM 更加容易受到外界因素的影响而发生错误,这些外界因素包括了:射线辐射、温度、灰尘、电子和磁场等外部因素。
位反转错误造成的结果可能是应用程序的奔溃,也可能是操作系统崩溃,最坏的情况就是业务程序使用了受到位反转错误污染的数据,却并不知道,程序依然在运行,这种错误被称为静默错误。
本以为内存芯片不会发生错误或者发生错误的概率非常低,但是事实并非如此,内存错误的发生概率远远超出人们的预期,并且内存错误是造成机器奔溃的三大原因之一。
内存错误
- 软错误:暂时性错误,芯片随即发生的错误,内存芯片并没有损坏。
- ECC:内存清洗机制。在内存空闲的时候对内存进行校验,如果发现内存单元中存在单个位错误,就会将纠正后的值重新写入到内存中,如果发生的是软错误,在 ECC 写内存后,这个错误就会消失;对于多个位发生错误的情况,ECC 目前无法进行纠正。
- 硬错误:内存芯片发生了永久性硬件错误,ECC 无法纠正。
RAS(Reliability、Availability、Serviceability)
- 可靠性:机器在某段给定的时间内,能够产生正确输出的概率。高可靠性的机器可以主动的采取措施避免、检测和修复硬件错误,在不能修复错误的情况下,就将错误进行主动隔离并报告给上层的修复机制,或将受影响的部分或整个系统暂停,并将错误报告给用户。
- 可用性:系统在给定时间内正常运行的概率。高可用性的计算机在发生硬件错误时,可以禁用发生故障的单元,以一种功能较少的状态继续运行。
- 可服务性:又称可维护性,指的是机器在发生故障之后,可以被修复的容易程度和修复的速度。
国内外研究现状
检测和处理内存错误。
硬件方面
- ECC:它是硬件方面内存检测与纠错机制的代表。在程序每次从内存读取数据时,都会对从内存读出的数据进行校验,如果发现数据有错误,就会进行纠正。受限于成本的原因,目前 ECC 只能对每个内存单元中发生的单个位错误进行纠正。
软件方面
区分离线型还是在线型的指标:能否与操作系统同时运行。
- 离线型
- Memtest86+:通常作为操作系统启动时的一个选择项供用户选择,即在机器启动时,操作系统和 Memtest86+ 只能选择其一,它直接运行在硬件之上,因此可以对内存进行任意的读写操作以及检测错误,它对内存独享。
- 在线型(破坏式内存检测算法:向待检测的内存(只检测它能够获取到的内存)中写入数据,然后再从这块内存将数据读出,如果读出地数据与写入地数据一致,就认为这块内存没有发生错误,否则就认为这块内存发生了错误)
- MCE(Machine Check Exception):Linux 内核提供给 Intel Pentium4、Xeon、Atom 和 P6 平台 18 号中断的中断服务例程,该号中断又被称为机器检测异常,专门用于处理硬件错误,这些硬件错误包括系统总线错误、ECC 错误、奇偶校验错误、硬件高速缓存错误和 TLB 错误。MCE 的处理流程中,很大的一部分是对内存错误的处理流程。该处理流程会根据错误的严重级别选择停止操作系统运行、杀死受影响的进程或者是恢复错误使系统继续正常运行。
- RAMpage:其检测内存的操作实现是在用户空间。RAMpage 作为 Linux 系统中的一个进程与 Linux 系统同时运行,它包括内核空间和用户空间两个部分。内核空间负责向操作系统申请内存,然后将申请到内存提供给用户空间以进行检测,这样做的原因是内核空间部分具有比用户空间部分更高的优先级,可以获取到用户空间不能获取的内存。RAMpage 实现为一个内存检测框架,使得软件层面实现的内存检测算法可以作为一个插件轻易地整合到整个系统中。
处于安全考虑,并不是 Linux 内核提供的所有机制都可以被内核模块使用,Linux 内核提供了一张内核符号表,只有通过内核的导出机制将相应的功能(包括函数和变量)导出到这张符号表中,才能被内核模块使用。
类似下图?
kernel/blk_drv/blk_drv.a(ll_rw_blk.o) needed due to _ll_rw_block
kernel/blk_drv/blk_drv.a(floppy.o) needed due to _do_floppy
kernel/blk_drv/blk_drv.a(hd.o) needed due to _do_hd
kernel/blk_drv/blk_drv.a(ramdisk.o) needed due to _rd_load
kernel/chr_drv/chr_drv.a(tty_io.o) needed due to _tty_table
...
lib/lib.a(wait.o) text 16f34(54), data 1d1e0(0), bss 1dd6b(0) hex
lib/lib.a(string.o) text 16f88(340), data 1d1e0(0), bss 1dd6b(0) hex
Global symbols:
_dup: 0x16ed4
_nmi: 0x8e28
_bmap: 0xc3a8
_iput: 0xc3f8
_blk_dev_init: 0x10f6c
_open: 0x16e64
_do_execve: 0xe458
_con_init: 0x15d74
_put_super: 0xd42c
_sys_setgid: 0x9b84
_sys_umask: 0x9f84
_con_write: 0x1500c
_show_task: 0x6a74
_buffer_init: 0xd284
_sys_settimeofday: 0x9f7c
_sys_getgroups: 0x9f0c
...
_sched_init: 0x72bc
_end: 0x1fe48
_gdt: 0x5cb8
_super_block: 0x1fae8
_sync_inodes: 0xc0f8
_idt: 0x54b8
_sys_write: 0xbf6c
_int3: 0x8e2f
Local symbols of boot/head.o:
startup_32: 0x0
setup_idt: 0x6f
setup_gdt: 0x9f
check_x87: 0x5a
after_page_tables: 0x5400
ignore_int: 0x5428
rp_sidt: 0x8c
idt_descr: 0x54aa
gdt_descr: 0x54b2
pg0: 0x1000
pg1: 0x2000
pg2: 0x3000
pg3: 0x4000
setup_paging: 0x5450
int_msg: 0x5414
Local symbols of init/main.o:
gcc_compiled.: 0x64b8
_time_init: 0x64b8
_memory_end: 0x18000
_buffer_memory_end: 0x18004
_main_memory_start: 0x18008
_printf: 0x67b0
_printbuf: 0x1d1e0
_argv_rc: 0x1800c
_envp_rc: 0x18014
_argv: 0x18020
_envp: 0x18028
Local symbols of kernel/kernel.o:
sched.o: 0x6a34
gcc_compiled.: 0x6a34
_init_task: 0x18194
_wait_motor: 0x192ac
_mon_timer: 0x192bc
_moff_timer: 0x192cc
_next_timer: 0x192e0
_timer_list: 0x1d5e0
system_call.o: 0x7404
SIG_CHLD: 0x11
EAX: 0x0
EBX: 0x4
ECX: 0x8
EDX: 0xc
FS: 0x10
ES: 0x14
DS: 0x18
EIP: 0x1c
CS: 0x20
EFLAGS: 0x24
OLDESP: 0x28
OLDSS: 0x2c
state: 0x0
counter: 0x4
priority: 0x8
signal: 0xc
sigaction: 0x10
blocked: 0x210
sa_handler: 0x0
sa_mask: 0x4
sa_flags: 0x8
sa_restorer: 0xc
...
signal.o: 0xa710
gcc_compiled.: 0xa710
mktime.o: 0xa984
gcc_compiled.: 0xa984
_month: 0x19318
Local symbols of mm/mm.o:
memory.o: 0xaa04
gcc_compiled.: 0xaa04
_HIGH_MEMORY: 0x1934c
_mem_map: 0x19350
_try_to_share: 0xb350
page.o: 0xb858
Local symbols of fs/fs.o:
open.o: 0xb890
gcc_compiled.: 0xb890
read_write.o: 0xbd7c
gcc_compiled.: 0xbd7c
....
gcc_compiled.: 0x10b60
_free_ind: 0x10b60
_free_dind: 0x10bc4
select.o: 0x10cc4
gcc_compiled.: 0x10cc4
Local symbols of kernel/blk_drv/blk_drv.a(ll_rw_blk.o):
gcc_compiled.: 0x10ccc
_make_request: 0x10d18
Local symbols of kernel/blk_drv/blk_drv.a(floppy.o):
gcc_compiled.: 0x10f98
_recalibrate: 0x1a9ec
_reset: 0x1a9f0
...
_reset_interrupt: 0x12504
_floppy_on_interrupt: 0x12b1c
Local symbols of kernel/blk_drv/blk_drv.a(hd.o):
gcc_compiled.: 0x12b6c
_recalibrate: 0x1aad4
_reset: 0x1aad8
_NR_HD: 0x1ab0c
_hd: 0x1ab10
_callable.0: 0x1ab60
_reset_hd: 0x12f94
_recal_intr: 0x13574
_read_intr: 0x13188
_write_intr: 0x13390
Local symbols of kernel/blk_drv/blk_drv.a(ramdisk.o):
gcc_compiled.: 0x13db0
Local symbols of kernel/chr_drv/chr_drv.a(tty_io.o):
gcc_compiled.: 0x142a8
_cr_flag.0: 0x1d0a0
Local symbols of kernel/chr_drv/chr_drv.a(console.o):
gcc_compiled.: 0x14bcc
_state: 0x1d0a4
_ques: 0x1d0a8
_attr: 0x1d0ac
...
_saved_y: 0x1d0b4
_x: 0x1dd3f
_sysbeep: 0x15f98
_video_page: 0x1dd5d
Local symbols of kernel/chr_drv/chr_drv.a(keyboard.o):
size: 0x400
head: 0x4
tail: 0x8
...
none: 0x16398
minus: 0x16399
die: 0x167c9
Local symbols of kernel/chr_drv/chr_drv.a(serial.o):
gcc_compiled.: 0x167cc
Local symbols of kernel/chr_drv/chr_drv.a(rs_io.o):
size: 0x400
rs_addr: 0x0
head: 0x4
tail: 0x8
proc_list: 0xc
buf: 0x10
startup: 0x100
rs_int: 0x16921
rep_int: 0x16939
end: 0x16956
jmp_table: 0x16964
modem_status: 0x16974
write_char: 0x169b4
read_char: 0x16984
line_status: 0x1697c
write_buffer_empty: 0x169f4
Local symbols of kernel/chr_drv/chr_drv.a(tty_ioctl.o):
gcc_compiled.: 0x16a0c
_quotient: 0x1d0bc
Local symbols of kernel/math/math.a(math_emulate.o):
gcc_compiled.: 0x16d80
Local symbols of lib/lib.a(ctype.o):
gcc_compiled.: 0x16e54
Local symbols of lib/lib.a(_exit.o):
gcc_compiled.: 0x16e54
Local symbols of lib/lib.a(open.o):
gcc_compiled.: 0x16e64
Local symbols of lib/lib.a(close.o):
gcc_compiled.: 0x16e8c
Local symbols of lib/lib.a(write.o):
gcc_compiled.: 0x16eac
Local symbols of lib/lib.a(dup.o):
gcc_compiled.: 0x16ed4
Local symbols of lib/lib.a(setsid.o):
gcc_compiled.: 0x16ef4
Local symbols of lib/lib.a(execve.o):
gcc_compiled.: 0x16f0c
Local symbols of lib/lib.a(wait.o):
gcc_compiled.: 0x16f34
Local symbols of lib/lib.a(string.o):
gcc_compiled.: 0x16f88