GUID, Globally Unique Identifier, aka UUID(Universally Unique Identifier), is very useful when you need a global identifier in you program.
GUID is a 128-bit integer number used to identify resources. The term GUID is generally used by developers working with Microsoft technologies, while UUID is used everywhere else.
For more information, you can visit:
1. IETF: RFC 4122 – http://www.ietf.org/rfc/rfc4122.txt (There’s a full implementation UUID in the Appendix A)
2. Wikipedia: Globally Unique Identifier – http://en.wikipedia.org/wiki/Globally_Unique_Identifier
3. Microsoft: GUID Structure – http://msdn2.microsoft.com/en-us/library/aa373931.aspx
Here is a simple/sample implementation of generating a GUID for yourself.
typedef struct { unsigned char m_abyMacAddress[6]; unsigned char m_abyTime[8]; BOOL m_bClock_seq_change; } uCID; typedef struct { u32 m_dwStartTime; u32 m_dwStartMilliTime; u32 m_dwOldMilliTime; u8 m_abyLastTime[8]; BOOL m_bNotStart; BOOL m_bGenerated; uCID m_tUCID; u8 m_abyCid[16]; u8 m_abyOldCid[16]; u16 m_wClock_seq; } cidLocalStorage; u32 timerGetTimeInMilliseconds(void) { #ifdef __VXWORKS__ u32 dwTicks, dwTicksPerSec; u32 t; dwTicks = tickGet(); dwTicksPerSec = sysClkRateGet(); t = dwTicks / dwTicksPerSec * 1000 + (dwTicks % dwTicksPerSec) * 1000 / dwTicksPerSec; return (t==0xffffffff)?0:t; #elif _UNIX_ u32 t; static u32 sSeconds=0; struct timeval tv; /* timeval structure */ gettimeofday(&tv, NULL); if (!sSeconds) sSeconds=(u32)tv.tv_sec; t=(u32)( (tv.tv_sec - sSeconds)*1000 + (tv.tv_usec/1000) ); return (t==0xffffffff)?0:t; //modify by yj for CID [20120424] #elif _LINUX_ u32 t; static u32 sSeconds=0; struct timeval tv; /* timeval structure */ gettimeofday(&tv, NULL); if (!sSeconds) sSeconds=(u32)tv.tv_sec; t=(u32)( (tv.tv_sec - sSeconds)*1000 + (tv.tv_usec/1000) ); return (t==0xffffffff)?0:t; //end #elif WIN32 return GetTickCount(); #endif } u32 timerGetTimeInSeconds(void) { //long only to 2036 return (time(NULL))&0x7fffffff; /* force positive time */ } u32 GetRandomNumber(void) { s32 random; u32 result; /* for non windows systems, supply a permanant seed */ static u32 seeded; if (!seeded) { srand(timerGetTimeInMilliseconds()); seeded=TRUE; } random = rand(); result = timerGetTimeInMilliseconds() * (random + 1); return result; } #define FROM1900TILL1970 (u32)0x83AA7E80// cidLocalStorage *GetTime(u8 *theTime, BOOL32 *clockSeqChange) { u32 milliTime; u32 secTime; static cidLocalStorage cidTls = {0}; if (!cidTls.m_dwStartTime) { cidTls.m_dwStartTime=timerGetTimeInSeconds()/3*5+0xb21dd213u; cidTls.m_dwStartMilliTime=timerGetTimeInMilliseconds(); } if(!cidTls.m_wClock_seq) { cidTls.m_wClock_seq = (u16)GetRandomNumber(); } milliTime = timerGetTimeInMilliseconds()-cidTls.m_dwStartMilliTime; *clockSeqChange = (!cidTls.m_bNotStart) || /* first time */ ((s32)milliTime<0) || /* after reboot or overflow */ ((cidTls.m_dwOldMilliTime - milliTime) == 0); /* in the same millisec as before */ cidTls.m_bNotStart = TRUE; cidTls.m_dwOldMilliTime = milliTime; secTime=milliTime/600+cidTls.m_dwStartTime; milliTime%=600; milliTime*=27777; theTime[0]=2; theTime[1]=(unsigned char)(secTime>>24); theTime[2]=(unsigned char)(secTime>>16); theTime[3]=(unsigned char)(secTime>>8); theTime[4]=(unsigned char)(secTime); theTime[5]=(unsigned char)(milliTime>>16); theTime[6]=(unsigned char)(milliTime>>8); theTime[7]=(unsigned char)(milliTime); return &cidTls; } //TODO to be implemented, hard code a MAC address void GetMACaddress(unsigned char*theMAC) { theMAC[0]=0x56; theMAC[1]=0x34; theMAC[2]=0x34; theMAC[3]=0x34; theMAC[4]=0x34; theMAC[5]=0xef; } // u8* GenerateGUID(void) { uCID u; /* set time_low , time_mid, time_hi_and_version fields - 0-7 octets of cid */ cidLocalStorage * cidTls = GetTime(u.m_abyTime, &(u.m_bClock_seq_change)); memcpy(cidTls->m_abyCid,u.m_abyTime,8); memcpy(cidTls->m_tUCID.m_abyTime ,u.m_abyTime, sizeof(u.m_abyTime)); cidTls->m_tUCID.m_bClock_seq_change = u.m_bClock_seq_change; /* 4 most significant bits of 6-7 bytes set to version number - '0001' */ //2007.02.05 LINUX_ARM //*((u16*)(cidTls->m_abyCid+6)) &= 0x1ffff; u16 wCID; memcpy(&wCID, cidTls->m_abyCid+6, sizeof(wCID)); wCID &= 0x1ffff; memcpy(cidTls->m_abyCid+6, &wCID, sizeof(wCID)); /* set clock_seq_hi_and_reserved and clock_seq_low fields - 8,9 octets of cid */ if (u.m_bClock_seq_change) { cidTls->m_wClock_seq++; cidTls->m_wClock_seq %= 16384; /* 16384 - '0100000000000000' */ } cidTls->m_abyCid[9] = (u8) cidTls->m_wClock_seq; /* set clock_seq_low to the 8 LSBs*/ cidTls->m_abyCid[8] = (u8) (cidTls->m_wClock_seq>>8); /* set clock_seq_hi */ cidTls->m_abyCid[8] &= 0xbf; /* set 2 MSBs to '10' */ /* set node - 10 -15 octets of cid */ if (!cidTls->m_bGenerated) { cidTls->m_bGenerated=TRUE; GetMACaddress(cidTls->m_tUCID.m_abyMacAddress); } memcpy(cidTls->m_abyCid+10,cidTls->m_tUCID.m_abyMacAddress,6); memcpy(cidTls->m_abyOldCid, cidTls->m_abyCid, 16); return cidTls->m_abyCid; }
In fact, RFC4122 provided a full implementation of UUID in Appendix A – Sample Implementation. If you need to implement a strictly standard version of UUID/GUID, you can use that code directly.