3.3 EntropyService分析
根据物理学基本原理,一个系统的熵越大,该系统就越不稳定。在Android中,目前也只有随机数常处于这种不稳定的系统中了。
SystemServer中添加该服务的代码如下:
ServiceManager.addService("entropy",new EntropyService());
上边代码非常简单,从中可直接分析EntropyService的构造函数:
[—>EntropyService.java:EntropyService构选函数]
public EntropyService(){
//调用另外一个构造函数,getSystemDir函数返回的是/data/system目录
this(getSystemDir()+"/entropy.dat","/dev/urandom");
}
public EntropyService(String entropyFile, String randomDevice){
this.randomDevice=randomDevice;//urandom是Linux系统中产生随机数的设备
///data/system/entropy.dat文件保存了系统此前的熵信息
this.entropyFile=entropyFile;
//下面有4个关键函数
loadInitialEntropy();//①
addDeviceSpecificEntropy();//②
writeEntropy();//③
scheduleEntropyWriter();//④
}
从以上代码中可以看出,EntropyService构造函数中依次调用了4个关键函数,这4个函数比较简单,这里只介绍它们的作用。感兴趣的读者可自行分析其代码。
loadInitialEntropy函数:将entropy.dat文件的中内容写到urandom设备,这样可增加系统的随机性。根据代码中的注释,系统中有一个entropy pool。在系统刚启动时,该pool中的内容为空,导致早期生成的随机数变得可预测。通过将entropy.dat数据写到该entropy pool(这样该pool中的内容就不为空)中,随机数的生成就无规律可言了。
addDeviceSpecificEntropy函数:将一些和设备相关的信息写入urandom设备。这些信息如下:
out.println("Copyright(C)2009 The Android Open Source Project");
out.println("All Your Randomness Are Belong To Us");
out.println(START_TIME);
out.println(START_NANOTIME);
out.println(SystemProperties.get("ro.serialno"));
out.println(SystemProperties.get("ro.bootmode"));
out.println(SystemProperties.get("ro.baseband"));
out.println(SystemProperties.get("ro.carrier"));
out.println(SystemProperties.get("ro.bootloader"));
out.println(SystemProperties.get("ro.hardware"));
out.println(SystemProperties.get("ro.revision"));
out.println(new Object().hashCode());
out.println(System.currentTimeMillis());
out.println(System.nanoTime());
该函数的注释表明,即使向urandom的entropy pool中写入固定信息,也能增加随机数生成的随机性。从熵的角度考虑,系统的质量越大(即pool中的内容越多),该系统越不稳定。
writeEntropy函数:读取urandom设备的内容到entropy.dat文件。
scheduleEntropyWriter函数:向EntropyService内部的Handler发送一个ENTROPY_WHAT消息。该消息每3小时发送一次。收到该消息后,EntropyService会再次调用writeEntropy函数,将urandom设备的内容写到entropy.dat中。
通过上面的分析可知,entropy.dat文件保存了urandom设备内容的快照(每3小时更新一次)。当系统重新启动时,EntropyService又利用这个文件来增加系统的熵,通过这种方式使随机数的生成更加不可预测。
注意 EntropyService本身的代码很简单,但是为了尽量保证随机数的随机性,Android还是下了一番苦功的。