通过升级C库解决了问题。
我想使用系统调用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? 因为它是一个新的&#34;系统调用,我该如何使用它?
编辑:
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时
或r = getrandom(buf,l,o)它是相同的..
答案 0 :(得分:8)
所以,似乎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;
}
答案 1 :(得分:5)
{1}}系统调用是在linux内核3.17中引入的。 Ubuntu 14.04随内核3.13一起提供,所以你必须更新到更新的内核才能获得系统调用。
要获取Ubuntu的linux内核的.deb包,请查看kernel.ubuntu.com。 askubuntu.com也讨论了这个问题。
答案 2 :(得分:4)
getrandom
and getentropy
were added to glibc in version 2.25。截至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
都会失败并将errno
设置为ENOSYS
在较旧的内核上运行。)
答案 3 :(得分:2)
我认为您的程序会出现分段错误。以下代码应该有效:
#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;
}
答案 4 :(得分:0)
在这里,我编译了之前显示的一些代码,并更正了错误,包括我的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;
}