我对手册页中的措辞感到困惑arch_prctl(2)
。具体来说,它指出:
64 位段基础的上下文切换相当昂贵。 通过使用 modify_ldt(2) 设置 LDT 或在内核 2.5 或更高版本中使用 set_thread_area(2) 系统调用,使用段选择器设置 32 位基数可能是更快的替代方法。仅当您要设置大于 4GB 的基础时才需要 arch_prctl()。可以通过使用带有 MAP_32BIT 标志的 mmap(2) 来分配前 2GB 地址空间中的内存。
这是否意味着使用此系统调用的进程的上下文切换将受到性能损失或确切的含义是什么?
在查看了 Linux 内核的源代码后,似乎对于小于 4 GiB 的地址使用 LDT,而大于 4 GiB 的地址使用特定于模型的寄存器。
case ARCH_SET_FS:
/* handle small bases via the GDT because that's faster to
switch. */
if (addr <= 0xffffffff) {
set_32bit_tls(task, FS_TLS, addr);
if (doit) {
load_TLS(&task->thread, cpu);
loadsegment(fs, FS_TLS_SEL);
}
task->thread.fsindex = FS_TLS_SEL;
task->thread.fs = 0;
} else {
task->thread.fsindex = 0;
task->thread.fs = addr;
if (doit) {
/* set the selector to 0 to not confuse
__switch_to */
loadsegment(fs, 0);
ret = wrmsrl_safe(MSR_FS_BASE, addr);
}
}
put_cpu();
break;
使用 GDT 如何比写入寄存器更快?另外,我假设更新 FS 和 GS 的价格仅在进程之间切换时支付,这意味着当没有其他进程计划运行时,通过系统调用进入内核没有额外成本?