首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux系统和errno

Linux系统和errno
EN

Stack Overflow用户
提问于 2016-05-11 15:29:13
回答 4查看 9.6K关注 0票数 8

上下文:为了更好地理解系统如何在Linux下工作,我正在尝试编写一个带有内联的小型C程序,该程序应该在x86_64系统上运行,并与gcc一起编译。

我的问题是:在这个环境中,syscall (例如写)是如何返回错误号的?我知道,当我使用像glibc这样的库时,它负责在全局errno变量中保存产生的错误代码。但是,当我通过内联汇编程序直接调用syscall时,错误号存储在哪里?它是存储在单独的寄存器中,还是用%rax编码?

让我们以linux上的写syscall为例:

当调用write时,在syscall返回之后,我发现它将0xfffffffffffffff2存储在%rax中,是否需要从其中提取错误代码?

如果我有错误代码号,应该在哪里查找以识别实际发生的错误?假设我返回了数字5,需要参考哪个头文件才能找到相应的符号错误名称。

我给写电话打电话是这样的:

代码语言:javascript
复制
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 */
    );

使用resultmsglen定义如下:

代码语言:javascript
复制
long result = 0;
char* msg = "Hello World\n";
long len = 12;
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-05-11 15:55:21

Linux的惯例是,它们为返回值中的成功调用同时编码可能的错误代码和返回值。只是glibc或其他C库的包装器将errno设置为底层syscall返回的错误代码,包装器将返回-1。以write为例,内核进行类似于以下内容的错误处理:

代码语言:javascript
复制
ssize_t write(int fd, ...) {
    if (fd is not valid)
         return -EBADF;
    return do_write(...);
}

因此,正如您所看到的,错误代码只是在返回值中,根据语义,总是有一种方法可以通过将它与一个不可能成功操作的值进行比较来检查syscall是否成功。对于大多数系统(如write )来说,这意味着检查它是否为负。

票数 10
EN

Stack Overflow用户

发布于 2016-05-11 15:55:13

架构调用约定

正如您已经猜到的,您不能使用errno,因为它是GLibC特异性。如果raxx86_64,您想要的信息将在x86_64中。手册页man 2 syscall有以下解释:

代码语言:javascript
复制
Architecture calling conventions

       Every architecture has its own way of invoking and passing arguments
       to the kernel.  The details for various architectures are listed in
       the two tables below.

       The first table lists the instruction used to transition to kernel
       mode (which might not be the fastest or best way to transition to the
       kernel, so you might have to refer to vdso(7)), the register used to
       indicate the system call number, the register used to return the
       system call result, and the register used to signal an error.

       arch/ABI    instruction           syscall #  retval  error    Notes
       ────────────────────────────────────────────────────────────────────
       alpha       callsys               v0         a0      a3       [1]
       arc         trap0                 r8         r0      -
       arm/OABI    swi NR                -          a1      -        [2]
       arm/EABI    swi 0x0               r7         r0      -
       arm64       svc #0                x8         x0      -
       blackfin    excpt 0x0             P0         R0      -
       i386        int $0x80             eax        eax     -
       ia64        break 0x100000        r15        r8      r10      [1]
       m68k        trap #0               d0         d0      -
       microblaze  brki r14,8            r12        r3      -
       mips        syscall               v0         v0      a3       [1]
       nios2       trap                  r2         r2      r7
       parisc      ble 0x100(%sr2, %r0)  r20        r28     -
       powerpc     sc                    r0         r3      r0       [1]
       s390        svc 0                 r1         r2      -        [3]
       s390x       svc 0                 r1         r2      -        [3]
       superh      trap #0x17            r3         r0      -        [4]
       sparc/32    t 0x10                g1         o0      psr/csr  [1]
       sparc/64    t 0x6d                g1         o0      psr/csr  [1]
       tile        swint1                R10        R00     R01      [1]
       x86_64      syscall               rax        rax     -        [5]
       x32         syscall               rax        rax     -        [5]
       xtensa      syscall               a2         a2      -

和笔记号[5]

代码语言:javascript
复制
[5] The x32 ABI uses the same instruction as the x86_64 ABI and
               is used on the same processors.  To differentiate between
               them, the bit mask __X32_SYSCALL_BIT is bitwise-ORed into the
               system call number for system calls under the x32 ABI.  Both
               system call tables are available though, so setting the bit
               is not a hard requirement.

(在该手册页中,下面是一个表,显示如何将参数传递给系统调用。这是一个有趣的阅读。)

如何在此环境中从syscall (例如写)返回错误号?

您必须检查您的rax寄存器的返回值。

票数 6
EN

Stack Overflow用户

发布于 2016-11-02 18:00:13

在Linux上,使用syscall程序集指令的系统调用失败将返回rax寄存器中的值-errno。所以在你的例子中,0-0xffffffffff 2,== 0xE,它是14,所以你的错误是14。

你怎么知道什么叫“差事14”?您应该在google上搜索"Linux错误代码表“,或者查看errno.h,这样就可以找到答案。

看看这里:http://www.virtsync.com/c-error-codes-include-errno

根据那张表,14是EFAULT,意思是“坏地址”。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37167141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档