我做到了 sudo cat /proc/1/maps -vv
我试图弄清楚输出.我可以看到很多共享库按预期映射到内存映射段.
7f3c00137000-7f3c00179000 r-xp 00000000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00179000-7f3c00379000 ---p 00042000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00379000-7f3c0037a000 r--p 00042000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037a000-7f3c0037b000 rw-p 00043000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037b000-7f3c00383000 r-xp 00000000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00383000-7f3c00583000 ---p 00008000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00583000-7f3c00584000 r--p 00008000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00584000-7f3c00585000 rw-p 00009000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00585000-7f3c0059b000 r-xp 00000000 08:01 21237220 /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0059b000-7f3c0079b000 ---p 00016000 08:01 21237220 /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0079b000-7f3c0079c000 r--p 00016000 08:01 21237220 /lib/x86_64-linux-gnu/libnih.so.1.0.0
Run Code Online (Sandbox Code Playgroud)
接近尾声有类似的东西
7f3c0165b000-7f3c0177e000 rw-p 00000000 00:00 0 [heap]
7fff97863000-7fff97884000 …Run Code Online (Sandbox Code Playgroud) 我正在我们的风暴监督员(Wheezy机器)上调试高系统CPU使用率(非用户CPU使用率).以下是观察结果
相关过程的输出输出:
Events: 10K cpu-clock
16.40% java [kernel.kallsyms] [k] system_call_after_swapgs
13.95% java [kernel.kallsyms] [k] pvclock_clocksource_read
12.76% java [kernel.kallsyms] [k] do_gettimeofday
12.61% java [vdso] [.] 0x7ffe0fea898f
9.02% java perf-17609.map [.] 0x7fcabb8b85dc
7.16% java [kernel.kallsyms] [k] copy_user_enhanced_fast_string
4.97% java [kernel.kallsyms] [k] native_read_tsc
2.88% java [kernel.kallsyms] [k] sys_gettimeofday
2.82% java libjvm.so [.] os::javaTimeMillis()
2.39% java [kernel.kallsyms] [k] arch_local_irq_restore
Run Code Online (Sandbox Code Playgroud)
在相关过程的线程中捕获了这一点
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000247 0 64038 gettimeofday
0.00 0.000000 0 1 rt_sigreturn
0.00 …Run Code Online (Sandbox Code Playgroud) 我正在使用perf工具来分析centos 6.5上的内核模块(内核版本:2.6.32-431.el6.x86_64).我已经分别安装了内核调试信息包.虽然我能够看到[kernel.kallsyms]函数列表,但是无法识别与[vdso]和[vsyscall]相关的符号并显示为十六进制数字.
有关如何添加这两个库的调试信息的任何想法?
我在最后一个libc中剖析了syscall调用:
git clone git://sourceware.org/git/glibc.git
Run Code Online (Sandbox Code Playgroud)
我在sysdeps/unix/sysv/linux/i386/sysdep.h中有这个代码:
# define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
LOADREGS_##nr(args) \
asm volatile ( \
"call *%%gs:%P2" \
: "=a" (resultvar) \
: "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \
ASMARGS_##nr(args) : "memory", "cc")
Run Code Online (Sandbox Code Playgroud)
如果我理解这段代码,那么LOADREGS _ ## nr(args)宏会将参数加载到寄存器ebx,ecx,edx,esi,edx和ebp中.
sysdeps/UNIX/SYSV/LINUX/I386/sysdep.h中
# define LOADREGS_0()
# define ASMARGS_0()
# define LOADREGS_1(arg1) \
LOADREGS_0 ()
# define ASMARGS_1(arg1) \
ASMARGS_0 (), "b" ((unsigned int) (arg1))
# define LOADREGS_2(arg1, arg2) \
LOADREGS_1 (arg1)
# define ASMARGS_2(arg1, arg2) \
ASMARGS_1 (arg1), "c" ((unsigned …Run Code Online (Sandbox Code Playgroud) 我在想,如果有一种方法来捕获(即观察)VDSO调用像gettimeofday在strace.
还有,有没有办法在不加载linux-vdso.so.1(标志或env变量)的情况下执行二进制文件?
最后,如果我编写一个程序linux-vdso.so.1从辅助向量中删除地址然后execve我的程序呢?有人试过吗?
我知道将 vdso=0 传递给内核可以关闭此功能,并且 glibc 中的动态链接器可以自动检测和使用内核中的 vdso 功能。
在这里我遇到了这个问题。在我的机构中有一个 RHEL 5.6 框(内核 2.6.18-238.el5),我只有普通用户访问权限,可能患有RHEL 错误 673616。
当我在其上编译 linux-headers-3.9/gcc-4.7.2/glibc-2.17/binutils-2.23 的工具链时,gcc bootstrap 在 stage2 中的 cc1 中失败无法运行
Program received signal SIGSEGV, Segmentation fault.
0x00002aaaaaaca6eb in ?? ()
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0x00002aaaaaaabba0 0x00002aaaaaac3249 Yes (*) /home/benda/gnto/lib64/ld-linux-x86-64.so.2
0x00002aaaaacd29b0 0x00002aaaaace2480 Yes (*) /home/benda/gnto/usr/lib/libmpc.so.3
0x00002aaaaaef2cd0 0x00002aaaaaf36c08 Yes (*) /home/benda/gnto/usr/lib/libmpfr.so.4
0x00002aaaab14f280 0x00002aaaab19b658 Yes (*) /home/benda/gnto/usr/lib/libgmp.so.10
0x00002aaaab3b3060 0x00002aaaab3b3b50 Yes (*) /home/benda/gnto/lib/libdl.so.2
0x00002aaaab5b87b0 0x00002aaaab5c4bb0 Yes (*) /home/benda/gnto/usr/lib/libz.so.1
0x00002aaaab7d0e70 0x00002aaaab80f62c Yes (*) /home/benda/gnto/lib/libm.so.6 …Run Code Online (Sandbox Code Playgroud) 考虑以下针对Linux x86_64的程序:
inf.s:
.global _start
.text
_start:
jmp _start
Run Code Online (Sandbox Code Playgroud)
这基本上是一个无限循环.
如果我链接并删除它,我得到一个ELF可执行文件:
$ gcc -nostdlib inf.s
$ ./a.out &
[1] 15862
$ cat /proc/15862/maps
00400000-00401000 r-xp 00000000 fc:00 11404632 a.out
7fffacdb8000-7fffacdd9000 rwxp 00000000 00:00 0 [stack]
7fffacddd000-7fffacdde000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Run Code Online (Sandbox Code Playgroud)
在ELF可执行文件中,第一个程序头LOAD包含占上述mmaps(a.out)中第一个条目的映射.(即使我删除每个,但是这个头和代码都会观察到相同的映射.) execve(2)调用ELF处理程序,fs/binfmt_elf.c其中读取程序头并在文件上调用mmap.
我不明白的是其他三个来自哪里(stack,vdso,vsyscall).它们未在ELF文件中提及,因此Linux内核必须默认设置这三个"匿名"或"特殊"映射.
我的问题是内核代码(或如何)Linux内核创建其他三个映射?他们是否继承了这个人?我似乎无法看到fs/exec.c它们的创建地点.
我一直在使用netmap估计最近宣布的英特尔错误对我的数据包处理应用程序的影响。到目前为止,我测量到每个poll()系统调用处理大约 50 个数据包,但这个数字不包括gettimeofday()调用。我还测量到每秒可以从不存在的文件描述符中读取 1650 万次(这大约是系统调用可以执行的最便宜的操作)。我的数据包处理速率是每秒176万个数据包,或者就系统调用而言,每秒0.352万个系统调用。这意味着如果系统调用惩罚加倍,性能将降低 0.0352 / 16.5 = 0.21333%,这几乎是我不应该担心的事情。
但是,我的应用程序可能gettimeofday()经常使用系统调用。我的理解是,这些不是真正的系统调用,而是作为虚拟系统调用实现的,如什么是 vdso 和 vsyscall?。
现在,我的问题是,对最近宣布的 Intel bug 的修复(也可能影响 ARM,但可能不会影响 AMD)是否会减慢gettimeofday()系统调用速度?或者是gettimeofday()由于作为不同类型的虚拟系统调用而实现的完全不同的动物?
我跟踪了一个 java 进程,该进程触发了大量内核时间来查看正在使用的系统调用,并且惊讶地看到它gettimeofday()并clock_gettime()占主导地位(我怀疑这是由于日志记录),考虑到以下man vdso状态,这很奇怪:
使用strace (1)跟踪系统调用时,vDSO 导出的符号(系统调用)不会出现在跟踪输出中。
这些系统调用是怎么发生的?有没有办法避免它们?
该机器在 EC2 上运行 Ubuntu 16.04.1。
为方便起见,我用 C ( testgtod.c)创建了一个最小的测试程序:
#include <stdlib.h>
#include <sys/time.h>
void main(void)
{
struct timeval tv;
for(int i = 0; i < 1000; i++) {
/* glibc wrapped, shouldn't actually syscall */
gettimeofday(&tv, NULL);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我在strace下编译并运行程序: gcc testgtod.c -o testgtod && sudo strace ./testgtod
输出包括对 gettimeofday() 的一千次调用,尽管我有预料。
我测试过的东西以确保我看不到东西:
确保二进制文件是一个 64 位精灵使用 file
ldd ./testgtod 确保 vDSO 处于活动状态:
linux-vdso.so.1 => (0x00007ffcee25d000) …
我在 Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz 上使用 CentOS Linux 7.3.1611 版
在我的用户空间应用程序测试期间,我注意到 clock_gettime(CLOCK_MONOTONIC, &ts) 可能需要 5-6 微秒而不是平均约 23 纳秒。它可能每 10000 次后续调用只发生一次,但是它可能会发生。
如果没有 VDSO 库,则可以解释。但是,VDSO 用于每个clock_gettime(我通过strace 检查过)。
无论相应的线程是否关联到某个 CPU 内核。不管这个CPU内核是否与操作系统隔离。这意味着测试应用程序可能会在独占 CPU 内核上运行,而无论如何可能会出现延迟!
我通过比较两个随后的 clock_gettime 调用的结果来测量延迟,例如:
unsigned long long __gettimeLatencyNs() {
struct timespec t1_ts;
struct timespec t2_ts;
clock_gettime(CLOCK_MONOTONIC, &t1_ts);
clock_gettime(CLOCK_MONOTONIC, &t2_ts);
return ((t2_ts.tv_sec - t1_ts.tv_sec)*NANO_SECONDS_IN_SEC + t2_ts.tv_nsec - t1_ts.tv_nsec);
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以分享一些想法,那里可能有什么问题?