Linux - 为什么自定义系统调用与负数无法正常工作?

Ber*_*pes 5 c linux int system-calls linux-kernel

我写了一个自定义系统调用,比较两个整数并返回最大的整数.这是我的内核端代码:

max.c

#include <linux/kernel.h>
#include <linux/syscalls.h>

asmlinkage long sys_max(int num1, int num2) 
{
  if (num1 > num2) 
  {
    return num1;
  }

  else 
  {
    return num2;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我的用户空间代码:

max.h

#include <unistd.h>
#define SYS_MAX 323

int max(int num1, int num2)
{
  int maxnumber = syscall(SYS_MAX, num1, num2);
  return maxnumber;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用这个小程序来测试系统调用:

#include <stdio.h>
#include <max.h>

int main()
{
    int a, b;
    scanf("%d", &a);
    scanf("%d", &b);
    printf("%d", max(a, b));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它对正数很有用,或者当一个是正数而另一个是负数时,但是当处理两个负值时,max总是返回-1.我想知道这是否是因为int-> long转换,但我似乎无法理解导致问题的原因.

hob*_*bbs 13

如果系统调用返回负值,则将其视为错误,并在libc中调用特殊错误处理代码.即,返回值被否定并移入errno全局变量,并且系统调用的返回值变为-1.

实际上,在阅读本文时,我发现在Linux上,只有-4095到-1的值被视为错误,但如果您希望函数处理任何可能的值,这既不可移植也不有用.

简而言之,您无法安全地使用系统调用的返回值来返回可能为负值的值.通常的惯例是传递指向目标变量的指针来保存结果,并保留成功/失败的返回码.请注意,使用系统调用执行此操作时,您将使用来自内核空间的用户空间指针,因此必须使用copy_to_user来编写结果.