我有一个非常简单的问题,但我整个周末都找不到任何答案。我正在使用sendto()
函数,它返回错误代码14:EFAULT。手册页将其描述为:
"An invalid user space address was specified for an argument."
我确信这是在谈论我指定的IP地址,但现在我怀疑它可能是它所指的消息缓冲区的内存地址 - 我找不到任何地方对此有任何澄清,任何人都可以清楚这一点吗?
谢谢, Ĵ
答案 0 :(得分:26)
EFAULT
如果某个参数的内存地址传递给sendto
(或者更常见的是传递给任何系统调用),则会发生这种情况。可以把它想象成一个关于你的系统调用的内核域SIGSEGV
。例如,如果你传递一个null或无效的缓冲区指针(用于读取,写入,发送,接收......),你就得到了
EFAULT
根本与IP地址无关。
答案 1 :(得分:0)
带有getcpu
为了使事情更具体,我们可以看一下getcpu
系统调用,它很容易理解,并显示相同的EFAULT行为。
从man getcpu
中我们看到签名是:
int getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache);
cpu
指向的内存将包含系统调用后正在运行进程的当前CPU的ID,唯一可能的错误是:
ERRORS
EFAULT Arguments point outside the calling process's address space.
因此我们可以使用以下方法进行测试:
main.c
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
int main(void) {
int err, ret;
unsigned cpu;
/* Correct operation. */
assert(syscall(SYS_getcpu, &cpu, NULL, NULL) == 0);
printf("%u\n", cpu);
/* Bad trash address == 1. */
ret = syscall(SYS_getcpu, 1, NULL, NULL);
err = errno;
assert(ret == -1);
printf("%d\n", err);
perror("getcpu");
return EXIT_SUCCESS;
}
编译并运行:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
样本输出:
cpu 3
errno 14
getcpu: Bad address
因此我们看到垃圾地址为1
的错误调用返回了14
,从内核代码https://stackoverflow.com/a/53958705/895245来看,这是EFAULT
请记住,系统调用本身会返回-14
,然后syscall
C包装程序会检测到由于负数导致的错误,返回-1
并设置errno
精确到实际的错误代码。
由于syscall非常简单,我们可以在kernel/sys.c
的内核5.4实现中对此进行确认:
SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
struct getcpu_cache __user *, unused)
{
int err = 0;
int cpu = raw_smp_processor_id();
if (cpup)
err |= put_user(cpu, cpup);
if (nodep)
err |= put_user(cpu_to_node(cpu), nodep);
return err ? -EFAULT : 0;
}
因此很显然,如果-EFAULT
存在问题,我们将返回put_user
。
值得一提的是,我的glibc在getcpu
中也有一个sched.h
包装器,但是在地址错误的情况下实现了段隔离,这有点令人困惑:How do I include Linux header files like linux/getcpu.h?但是这不是实际的系统调用对进程所做的,只是glibc使用该地址执行的操作。
在Ubuntu 20.04,Linux 5.4上进行了测试。
答案 2 :(得分:-1)
EFAULT是在文件“ include / uapi / asm-generic / errno-base.h”中定义的宏
#define EFAULT 14 /* Bad address */