生成函數為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