生成函数为php_session_create_id,看代码:
gettimeofday(&tv, NULL);
先获取当前时间,精确到毫微秒;
//看有没有$_SERVER['REMOTE_ADDR']
if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &array) == SUCCESS &&
Z_TYPE_PP(array) == IS_ARRAY &&
zend_hash_find(Z_ARRVAL_PP(array), "REMOTE_ADDR", sizeof("REMOTE_ADDR"), (void **) &token) == SUCCESS
) {
remote_addr = Z_STRVAL_PP(token);
}
//格式化
spprintf(&buf, 0, "%.15s%ld%ld%0.8F", remote_addr ? remote_addr : "", tv.tv_sec, (long int)tv.tv_usec, php_combined_lcg(TSRMLS_C) * 10);
IP地址+秒+毫微秒|php_combined_lcg函数返回的值;
看下php_combined_lcg这个函数
if (!LCG(seeded)) {
lcg_seed(TSRMLS_C);
}
MODMULT(53668, 40014, 12211, 2147483563L, LCG(s1));
MODMULT(52774, 40692, 3791, 2147483399L, LCG(s2));
z = LCG(s1) - LCG(s2);
if (z < 1) {
z += 2147483562;
}
return z * 4.656613e-10;
LCG表示LCG模块的全局变量,具体干什么的还没细看^_^
测试环境数据{s1 = 0, s2 = 0, seeded = 0}
再看MODMULT的定义
#define MODMULT(a, b, c, m, s) q = s/a;s=b*(s-a*q)-c*q;if(s<0)s+=m
为什么是这个算法,可以参考这里,乘余发生器算法:http://bbs.csdn.net/topics/60236316
最后再作MD5处理,这个算法可以在php.ini中处理,好像目前只支持md5和sha1算法;
注意最后结果算法出的字符串和php中计算的每两个字节的顺序可能不一样,C语言算出来是b06cd855f3dfe8846a68557b613b7ed9,而PHP算出来是0bc68d553ffd8e48a68655b716b3e79d
最终生成的长度还受session.session.hash_bits_per_character决定,这个默认是4,生出来的是32个字符,如果是6,则生成的长度为24