volatile是告诉编译器不要优化引用,这样每次读/写都不会使用存储在寄存器中的值,而是进行实际的内存访问.我可以理解它对一些普通变量有用,但不明白如何volatile影响指针.
volatile int *p = some_addr;
int a = *p; // CPU always has to load the address, then does a memory access anyway, right?
Run Code Online (Sandbox Code Playgroud)
如果它被宣布为有什么区别int *p = some_addr?
暂停指令通常用于测试自旋锁的循环,当一些其他线程拥有自旋锁时,以缓解紧密循环.据说这相当于一些NOP指令.有人能告诉我它是如何适用于自旋锁优化的吗?在我看来,即使是NOP指令也浪费了CPU时间.它们会降低CPU使用率吗?
另一个问题是我可以将暂停指令用于其他类似目的.例如,我有一个忙线程,它不断扫描一些地方(例如队列)以检索新节点; 但是,有时队列是空的,线程只是在浪费cpu时间.睡眠线程并通过其他线程唤醒它可能是一个选项,但线程是关键的,所以我不想让它睡觉.可以暂停指令工作以减轻CPU使用率吗?目前它使用100%cpu的物理核心?
谢谢.
我们如何在x86 Linux中直接使用sysenter/syscall实现系统调用?有人可以提供帮助吗?如果您还可以显示amd64平台的代码,那就更好了.
我知道在x86中,我们可以使用
__asm__(
" movl $1, %eax \n"
" movl $0, %ebx \n"
" call *%gs:0x10 \n"
);
Run Code Online (Sandbox Code Playgroud)
间接路由到sysenter.
但是我们如何使用sysenter/syscall直接编码来发出系统调用呢?
我找到了一些材料http://damocles.blogbus.com/tag/sysenter/.但仍然难以弄明白.
我正在编写一个将从汇编代码调用的C函数.
(具体来说,我想在linux内核的系统调用处理路径中做一些检查工作,所以我将在entry_32.S中调度系统调用之前调用c函数)
在定义我的c函数时,我对"asmlinkage"修饰符感到困惑.
我知道asmlinkage是告诉编译器参数将通过堆栈传递.
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
问题:
(1)在定义将从汇编代码调用的函数时是否需要asmlinkage?
(2)gcc中的默认调用约定是什么.如果我在定义交流功能时省略"asmlinkage",它是否意味着_cdecl或fastcall?
(3)如果默认调用约定是cdecl,为什么需要asmlinkage,考虑到cdecl等于asmlinkage修饰符?(我在这里纠正吗?)
(4)为什么那些系统调用函数都是用asmlinkage声明的.我们可以先将参数复制到寄存器中,然后调用那些系统调用函数吗?从我的角度来看,在x86中,当发出系统调用时,参数很容易保存在寄存器中; 那么为什么还要在堆栈中保存然后通过堆栈约定强制执行这样的传递参数呢?
最后,任何人都可以推荐一些我可以参考混合汇编/ c编程的资源/书籍吗?
我知道copy_to_user/ copy_from_user,get_user/ put_user函数就是为了这个目的.
我的问题是,给定一个用户空间地址/指针,如何从内核中访问地址所指向的数据?
我可以想象,首先我必须确保包含页面应该在物理内存中(而不是在磁盘中).
你下一步怎么做?我可以使用*p,其中p的指针指向某些用户空间中的数据,直接引用的数据?
或者我是否必须先调用kmap将包含的物理页面框架映射到内核虚拟地址空间?为什么?
我需要做一些实验,显示内联对我的代码的影响.有谁知道如何禁用sun jvm内联?我搜索了http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html并了解-XX:InlineSmallCode = n可以控制内联候选者的阈值.那么-xx:InlineSmallCode = 0会起作用吗?
我在一个程序中多次调用getpid()(为了测试系统调用的效率),但是当我strace用来获取trace时,只捕获了一个getpid()调用。
代码很简单:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void print_usage(){
printf("Usage: program count\n");
exit(-1);
}
int main(int argc, char** argv){
if(argc != 2)
print_usage();
int cnt = atoi(argv[1]);
int i = 0;
while(i++<cnt)
getpid();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用gdb并得到了这个:
(gdb) disasse
Dump of assembler code for function getpid:
0xb76faac0 <getpid+0>: mov %gs:0x4c,%edx
0xb76faac7 <getpid+7>: cmp $0x0,%edx
0xb76faaca <getpid+10>: mov %edx,%eax
0xb76faacc <getpid+12>: jle 0xb76faad0 <getpid+16>
0xb76faace <getpid+14>: repz ret
0xb76faad0 <getpid+16>: jne 0xb76faadc …Run Code Online (Sandbox Code Playgroud) 我理解字对齐,这使得 cpu 在将整数读入寄存器时只需要读取一次。
但是对于“双”是否需要8 字节对齐(假设是 32 位系统)?有什么好处?如果用于存储“double”的空间只是 4 字节对齐会发生什么?
我mprotect经常在我的程序中调用,一段时间后我发现程序失败了.我想这是由于mprotect电话太多,所以我写了一个测试来验证:
#define pagesize 4096
int main(){
while(1){
buffer = memalign(pagesize, 4 * pagesize);// allocate some buffer
mprotect(buffer, pagesize, PROT_NONE)// make the first page inaccessible
}
}
Run Code Online (Sandbox Code Playgroud)
在大约3万次迭代之后,无论缓冲区的大小如何,mprotect都返回-1.
任何人都可以解释为什么以及如何解决它?我的猜测是mprogtect消耗内核资源,每个进程都有一些约束,但不确定.