Bootstrap

Linux操作系统下取得UUID的方法

Linux下面,有专门生成UUID的命令:uuidgen [-r] [-t]。即可以生成一个32位的字符串。这个是在命令行得到。在/usr/include/lib里面有个/uuid/uuid.h,其中定义了个数据 uuid,无符号的字符指针。同时有专门生成UUID的函数:uuid_generate(uuid_t uu),生成的UUID放在参数UU里面。此时得到的结果是一个8位数的16进制数。

  在UUID生成函数的过程中经过了一些处理,才 生成的是8位的16进制数,原因在于,在它生成的过程中,本来生成的是32位的长整形,结果经过uuid_parse进行转换变成8位的16进制数。相 反,我们有uuid_unparse函数,可以反向将16进制数转换为32位的整形。

  注意的是:

  在linux下 要编译生成uuid函数的时候,我们要进行库的连接也就是最后要加上一个 –luuid。完全形式为:gcc –o uuid uuid.c –luuid。同时在定义保存变换的32位长整形的字符串时,我们要合理分配空间。最不安全的办法就是,申请一个指针去存放一个字符传,切忌避免这样做!

浅析linux下/dev/random和/dev/urandom如何生成随机数
// Copyright 2008 luther.gliethttp
#include
#include
#include

int main(int argc, char *argv[])
{
    int fd;
    char buf[256];
    int value;
    int i;
    struct timeval tv;

    fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
    if (fd == -1) fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK);
    if (read(fd, buf, 256) > 0) {
       
    }

    gettimeofday(&tv, 0);
    value = tv.tv_sec + tv.tv_usec;
    for (i = 0;i < 256;i++) {
        value += value*0xdeec + buf[i];
    }

    printf("%u", value);
    close(fd);
}

/dev/random和/dev/urandom是unix系统提供的产生随机数的设备,很多应用都需要使用random设备提供的随机数,比如ssh keys, SSL keys, TCP/IP sequence numbers等等。(/driver/char/random.c)

而random设备的random pool是从基于中断的IRQS里面取值,IRQS跟一些特殊的硬件绑定,基于这些硬件的interrupts将会提供给random设备。

linux下我们可以用cat /proc/interrupts 查看哪些设备绑定了irq

[oracle@test oracle]$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 135 0 0 301721845 IO-APIC-edge timer
1: 0 0 0 54 IO-APIC-edge keyboard
2: 0 0 0 0 XT-PIC cascade
8: 0 0 0 1 IO-APIC-edge rtc
14: 0 0 0 2 IO-APIC-edge ide0
16: 0 0 0 40 IO-APIC-level usb-uhci
18: 0 0 0 0 IO-APIC-level usb-uhci
19: 0 0 0 0 IO-APIC-level usb-uhci
23: 0 0 0 2257 IO-APIC-level ide2, ehci-hcd
25: 0 0 0 29 IO-APIC-level ioc1
26: 0 0 0 29 IO-APIC-level ioc0
48: 0 0 0 2151823972 IO-APIC-level eth0
82: 0 0 0 339588855 IO-APIC-level megaraid
NMI: 0 0 0 0
LOC: 301720634 301720634 301720634 301720633
ERR: 0
MIS: 0

来模拟一个从/dev/random取值但是/dev/random取不到足够值的情况,这时候取值的进程将会等待,直到得到足够的random 值。

[root@csdba ~]# time dd if=/dev/random of=1.dmp bs=1024k count=100

这时dd的进程将会hang住等待足够的random值

trace dd的进程在做什么

[root@csdba ~]# ps -ef|grep dd
root 4749 4156 0 17:11 pts/1 00:00:00 dd if /dev/random of 1.dmp bs 1024k count 100
root 4753 4634 0 17:12 pts/3 00:00:00 grep dd

[root@csdba ~]# strace -p 4749
Process 4749 attached - interrupt to quit
read(0,

dd的进程在等待读取足够的随机数,从上面我们可以看到eth0 网卡绑定了IRQS,那么我们进行网路传输的时候网卡将会提供很多interrupt 给/dev/random,既然这样,我们试着scp给这台机器一个文件看看。

[oracle@csdbc oracle]$ scp 1.dmp [email protected]:/
[email protected]’s password:
1.dmp 100% |***************************************************************************

再回到原来窗口看strace,可以发现strace已经结束,也就是dd已经完成

read(0, “E\347\276m\274\33\227-IZ5\330\264\245\260z\326\’\376\266″…, 1048576) = 44
write(1, “E\347\276m\274\33\227-IZ5\330\264\245\260z\326\’\376\266″…, 44) = 44
munmap(0xb7cb5000, 1060864) = 0
open(”/usr/share/locale/locale.alias”, O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2528, …}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7db7000
read(3, “# Locale name alias data base.\n#”…, 4096) = 2528
read(3, “”, 4096) = 0
close(3) = 0
munmap(0xb7db7000, 4096) = 0
open(”/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(”/usr/share/locale/en/LC_MESSAGES/coreutils.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, “0+100 records in\n”, 17) = 17
write(2, “0+100 records out\n”, 18) = 18
close(0) = 0
close(1) = 0
exit_group(0) = ?
Process 4749 detached

再看看dd的窗口

[root@csdba ~]# time dd if=/dev/random of=1.dmp bs=1024k count=100
0+100 records in
0+100 records out
real 4m19.484s
user 0m0.000s
sys 0m0.004s

果然dd已经结束,这个过程也验证了/dev/random是基于IRQS产生随机数的。

看过/dev/random后再来看看/dev/urandom

[root@csdba ~]# time dd if=/dev/urandom of=1.dmp bs=1024k count=100
100+0 records in
100+0 records out
real 0m21.758s
user 0m0.002s
sys 0m21.752s

很明显/dev/urandom和/dev/random有区别,/dev/urandom不受interrupts的限制,即使没有足够的interrupt它也能通过 random number generator产生足够的输出值,所以它不会导致dd hang.

另外还有一个很有意思的事情

当我们在linux上执行time dd if=/dev/random of=1.dmp bs=1024k count=100,dd虽然会hang住,但是可以用ctrl+c或kill命令中止dd,这是因为linux的dd会工作在用户模式。

但是我们遇到过在aix上执行 dd if=/dev/random of=1.dmp bs=1024k count=100,dd进程会导致占用一个单独的cpu,当dd读取一个bs的时候它进入内核模式,它将不能被ctrl+c或kill -9中断,只有当它读完一个bs后会把控制权返回给用户,这样的话就面临着如果bs值设置过大的时候会导致dd进程从/dev/random里面读不到足 够的值而一直处于内核模式,dd的进程将会一直消耗cpu直到/dev/random提供了新的值。由于dd命令在aix和linux处理的方式不同,所 以在aix上多采用/dev/urandom来产生随机数
;