首页 > 解决方案 > Linux系统调用何时触发段错误与返回EFAULT?

问题描述

我试图了解何时clock_gettime()会导致错误。手册页列出了以下两种可能性:

  1. EFAULT tp 指向可访问地址空间之外。
  2. EINVAL 此系统不支持指定的 clk_id。

很容易触发EINVAL错误,但我无法clock_gettime()设置errnoEFAULT. 相反,内核发送一个 SIGSEGV 信号来终止程序。例如,在以下代码中:

#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

int main()
{
    struct timespec tp;
    double time;

    if (clock_gettime(CLOCK_MONOTONIC, &tp + 4096) == -1) {
        if (errno == EINVAL) {
            perror("EINVAL");
            return EXIT_FAILURE;
        } else if (errno == EFAULT) {
            perror("EFAULT");
            return EXIT_FAILURE;
        } else {
            perror("something else");
            return EXIT_FAILURE;
        }
    }

    time = tp.tv_sec + 1e-9 * tp.tv_nsec;
    printf("%f\n", time);
}

Linux 内核如何在触发分段错误和让系统调用返回之间做出选择-EINVAL?什么时候会选择做后者?如果内核总是发送信号,是否真的需要检查是否errno等于EFAULT

我正在运行 Linux 内核 4.15,并使用(使用 clang v6.0)编译了该程序: clang -g -O0 -Wall -Wextra -Wshadow -Wstrict-aliasing -ansi -pedantic -Werror -std=gnu11 file.c -o file

标签: clinuxerror-handlingsystem-callsvdso

解决方案


clock_gettime可能不是作为系统调用执行,而是在用户空间中作为vdso的一部分执行。syscall如果您实际上通过使用with作为参数的函数来执行系统调用SYS_clock_gettime,我希望您会看到EFAULT.

话虽如此,EFAULT您不应该期望能够依赖它。一旦您将无效指针传递给需要有效指针作为其接口契约一部分的函数,您就会有未定义的行为,并且段错误或错误只是众多可能的表现形式之一。从这个角度来看,这是一个EFAULT甚至被记录在案的错误。


推荐阅读