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
_
rをint r = syscall(SYS_getrandom, buf, l, o);
またはr = getrandom(buf、l、o)に置き換えると、同じになります。
したがって、getrandom
はnot関数であり、単なるシステムコールのようです。
したがって、これが必要です。
/* 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
とgetentropy
はバージョン2.25で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
は失敗し、古いカーネルで実行した場合はerrno
をENOSYS
に設定します。)
getrandom()
syscallは、Linuxカーネル3.17で導入されました。 Ubuntu 14.04にはカーネル3.13が同梱されているため、syscallを取得するには、より新しいカーネルに更新する必要があります。
Ubuntu用のLinuxカーネルの.debパッケージを入手するには、 kernel.ubuntu.com を参照してください。この問題は askubuntu.com でも議論されました。
あなたのプログラムでは、セグメンテーション違反が発生すると思います。次のコードが機能するはずです。
#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;
}