【发布时间】:2016-09-07 02:53:47
【问题描述】:
上下文:我正在尝试使用内联 asm 编写一个小型 C 程序,该程序应在 x86_64 系统上的 Linux 下运行并使用 gcc 编译,以便更好地了解系统调用在 Linux 下的工作方式。
我的问题是:在这种环境中,系统调用(例如写入)如何返回错误号?我知道当我使用诸如 glibc 之类的库时,它会负责将生成的错误代码保存在全局 errno 变量中。但是当我通过内联汇编器直接调用系统调用时,错误号存储在哪里?它会被存储在一个单独的寄存器中,还是被编码为%rax?
以linux上的write系统调用为例:
当调用write 然后在系统调用返回后我发现它在%rax 中存储了0xfffffffffffffff2,我需要
以某种方式从中提取错误代码?
如果我有错误代码编号,我应该在哪里查找实际发生的错误?假设我得到了返回的数字 5,我需要查阅哪个头文件才能找到相应的符号错误名称。
我这样调用 write 系统调用:
asm ("mov $1,%%rax;"
"mov $1,%%rdi;"
"mov %1,%%rsi;"
"mov %2,%%rdx;"
"syscall;"
"mov %%rax,%0;"
: "=r" (result)
: "r" (msg), "r" (len)
: "%rdx", "%rsi", "%rax", "%rdi" /* EDIT: this is needed or else the registers will be overwritten */
);
result、msg 和 len 定义如下:
long result = 0;
char* msg = "Hello World\n";
long len = 12;
【问题讨论】:
-
asm调用syscall后,查看errno的内容,应该还在里面。
-
@PierreEmmanuelLallemant 否
errno由 glibc 或正在使用的任何 C 标准库定义。如果我不使用这样的库,那么我需要手动从寄存器中获取错误号。尝试使用errno时出现以下编译错误:error: ‘errno’ undeclared (first use in this function) -
我对此有很早(20 年)的了解,所以这可能不再正确,但 Linux 过去(有时仍然如此)将任何负返回值视为错误,并且那是错误号。
-
发布的错误是 EFAULT
-
您说内核中使用的“errno”可能与C wrap函数包装的errno不同,但是(经过简单的转换)我能想到的唯一情况是
close(),即在 Linux 中返回EINTR的失败案例,现在 POSIX 说应该是EINPROGRESS: ewontfix.com/4
标签: c linux system-calls