我一直在CentOs6.6中成功运行我的应用程序。最近,硬件(主板和RAM)已经更新,我的应用程序现在已经完全没有任何理由被杀死了。
[root@localhost PktBlaster]# ./PktBlaster
Killed
文件和ldd输出
[root@localhost PktBlaster]# file PktBlaster
PktBlaster: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
[root@localhost PktBlaster]# ldd PktBlaster
not a dynamic executable
strace的输出
[root@localhost PktBlaster]# strace ./PktBlaster
execve("./PktBlaster", ["./PktBlaster"], [/* 30 vars */] <unfinished ...>
+++ killed by SIGKILL +++
Killed
GDB
[root@localhost PktBlaster]# gdb PktBlaster
(gdb) break main
Breakpoint 1 at 0x43d664: file VTP.c, line 544.
(gdb) run
Starting program: /root/Veryx/PktBlaster/PktBlaster
During startup program terminated with signal SIGKILL, Killed.
调试时,发现bss内存很大(~6GB)。该系统有4GB内存,我认为这可能是问题的原因。
[root@localhost PktBlaster_1Gig]# size build/unix/bin/PktBlaster
text data bss dec hex filename
375551 55936 6747541120 6747972607 19235e3ff build/unix/bin/PktBlaster
该应用程序包含许多.h
个文件和许多数据结构,因此我很难确定为什么BSS被提升到6GB。
有人可以建议如何识别导致此问题的文件?或者其他更简单的调试方法?
答案 0 :(得分:2)
似乎问题确实是巨大的BSS大小。
我已要求您在评论中显示LD_DEBUG=all /lib64/ld-linux-x86-64.so.2 /path/to/exe
的输出。
/lib64/ld-linux-x86-64.so.2
是运行时链接程序,操作系统使用它在execve
系统调用期间将二进制文件加载到进程内存中。运行时链接程序负责解析可执行格式,加载内存中的所有部分和依赖项,执行所有必需的重定位等。
将环境变量LD_DEBUG
设置为我们指示运行时链接程序生成调试输出的所有内容。
[root @ localhost PktBlaster]#LD_DEBUG = all /lib64/ld-linux-x86-64.so.2 /根/ Veryx / PktBlaster / PktBlaster 851:file = / root / Veryx / PktBlaster / PktBlaster [0];生成链接图 / root / Veryx / PktBlaster / PktBlaster:加载共享时出错 库:/ root / Veryx / PktBlaster / PktBlaster:无法映射零填充 pages:无法分配内存
在运行时链接器的源代码(glibc-2.17 elf / dl-load.c,lines~1400)中搜索此错误消息,我们看到:
1393 if (zeroend > zeropage)
1394 {
1395 /* Map the remaining zero pages in from the zero fill FD. */
1396 caddr_t mapat;
1397 mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
1398 c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
1399 -1, 0);
1400 if (__builtin_expect (mapat == MAP_FAILED, 0))
1401 {
1402 errstring = N_("cannot map zero-fill pages");
1403 goto call_lose_errno;
1404 }
dl-loader正在加载BSS段,通过优化将二进制格式存储为只是字节数,必须初始化为零。 Loader尝试通过mmap
零初始化内存块(MAP_ANONYMOUS)进行分配,并从操作系统中获取错误:
15 #define ENOMEM 12 /* Out of memory */
来自man 2 mmap:
ENOMEM没有可用内存,或进程的最大数量 映射会被超过。
因此,无论出于何种原因,操作系统似乎都无法满足内存的加载程序请求。使用了一些限制(systemd,进程限制,一些安全LKM,无论如何)或者内核中没有足够的可用内存。
要确定哪个目标文件生成BSS的大部分内容 - 请使用
objdump -j '.bss' -t *.o