繁体   English   中英

找不到C中的getrandom系统调用

[英]getrandom syscall in C not found

通过升级C库解决了该问题。


我想使用syscall getrandom( http://man7.org/linux/man-pages/man2/getrandom.2.html

gcc-5 -std = c11 test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <linux/random.h>
#include <sys/syscall.h>

int main(void)
{
        void *buf = NULL;
        size_t l = 5;
        unsigned int o = 1;
        int r = syscall(SYS_getrandom, buf, l, o);
        return 0;
}

要么

 int main(void)
    {
            void *buf = NULL;
            size_t l = 5;
            unsigned int o = 1;
            int r = getrandom(buf, l, o);
            return 0;
    }

无论如何,当我尝试用gcc-5编译它时:

test.c: In function ‘main’:
test.c:14:17: warning: implicit declaration of function ‘getrandom’ [-Wimplicit-function-declaration]
         int r = getrandom(buf, l, o);
                 ^
/tmp/ccqFdJAJ.o: In function `main':
test.c:(.text+0x36): undefined reference to `getrandom'
collect2: error: ld returned 1 exit status

我正在使用Ubuntu 14.04,我该怎么做才能使用getrandom? 因为它是一个“新的”系统调用,我该如何使用它?

编辑:

uname -r
-> 4.0.3-040003-generic #201505131441 SMP Wed May 13 13:43:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

当我用int r = syscall(SYS_getrandom, buf, l, o);替换r时int r = syscall(SYS_getrandom, buf, l, o); 或者r = getrandom(buf,l,o)它是一样的..

因此,似乎getrandom 不是一个函数,只是一个系统调用。

因此需要这样做:

/* Note that this define is required for syscalls to work. */
#define _GNU_SOURCE

#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main(int arg, char *argv[])
{
        void *buf = NULL;
        size_t l = 5;
        unsigned int o = 1;
        int r = syscall(SYS_getrandom, buf, l, o);
        return 0;
}

getrandom()系统调用是在linux内核3.17中引入的。 Ubuntu 14.04随内核3.13一起提供,所以你必须更新到更新的内核才能获得系统调用。

要获取Ubuntu的linux内核的.deb包,请查看kernel.ubuntu.com askubuntu.com也讨论了这个问题。

在版本2.25中, getrandomgetentropy被添加到glibc中 截至2017年7月,大多数Linux发行版尚未更新到此版本(例如Debian最新发布的版本,刚刚发布,有2.24版),但很快就会发布。

以下是如何使用glibc包装器(如果可用),如果不是,则回退到原始系统调用:

#define _GNU_SOURCE 1
#include <sys/types.h>
#include <unistd.h>

#if defined __GLIBC__ && defined __linux__

# if __GLIBC__ > 2 || __GLIBC_MINOR__ > 24
#  include <sys/random.h>

int
my_getentropy(void *buf, size_t buflen)
{
    return getentropy(buf, buflen);
}

# else /* older glibc */
#  include <sys/syscall.h>
#  include <errno.h>

int
my_getentropy(void *buf, size_t buflen)
{
    if (buflen > 256) {
        errno = EIO;
        return -1;
    }
    return syscall(SYS_getrandom, buf, buflen, 0);
}

# endif

#else /* not linux or not glibc */
#error "Need implementation for whatever operating system this is"

#endif

(正如其他答案中所指出的,还有必要确保你有内核3.17或更新。如果在较旧的内核上运行,上述版本的my_getentropy都将失败并将errnoENOSYS 。)

我认为你的程序会出现分段错误。 以下代码应该有效:

#include <iostream>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main() {
  unsigned long int s;
  syscall(SYS_getrandom, &s, sizeof(unsigned long int), 0);
  std::cout << "The seed is: " << s << "." << std::endl;
}

在这里,我编译了之前显示的一些代码,并更正了错误,包括我的输出来自gcc -v进行比较。

// $ gcc -v
// Using built-in specs.
// COLLECT_GCC=gcc
// COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
// Target: x86_64-linux-gnu
// Configured with: ../src/configure -v --with-pkgversion='Ubuntu
//   5.4.0-6ubuntu1~16.04.9' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs
//   --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
//   --program-suffix=-5 --enable-shared --enable-linker-build-id
//   --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
//   --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
//   --enable-libstdcxx-debug --enable-libstdcxx-time=yes
//   --with-default-libstdcxx-abi=new --enable-gnu-unique-object
//   --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib
//   --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo
//   --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home
//   --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64
//   --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64
//   --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
//   --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
//   --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib
//   --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu
//   --host=x86_64-linux-gnu --target=x86_64-linux-gnu
// Thread model: posix
// gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)

//#define _GNU_SOURCE

#include <stdio.h>

#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main (int arg, char **argv)
{
  size_t length = 5;
  unsigned char buf[length];
  int r = syscall(SYS_getrandom, buf, length, 0);

  if (r != 0)
  {
    int iIter;
    printf ("random %zu bytes = ",length);
    for (iIter = 0 ; iIter < length-1 ; iIter++)
    {
      printf ("%02x:", buf[iIter]);
    }
    printf ("%02x\n", buf[iIter]);
  }
  else
  {
    perror ("syscall (SYS_getrandom, ...)");
  }
  return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM