= mlog = ÀÛ¼ºÇÒ ÇÁ·Î±×·¥ÀÌ ½ÃÀÛÇÑ ÈÄ ±Ý¹æ ³¡³ª°Å³ª ºü¸¥ ½Ã°£³»¿¡ ¿©·¯¹ø ½ÇÇàÇÏ´Â °ÍÀ̶ó¸é, ¹ö±×°¡ ¹ß»ýÇßÀ» ¶§ µð¹ö±ëÇϱ⠽±½À´Ï´Ù. ¿Ö³ÄÇϸé, ¹ö±×°¡ ¹ß»ýÇÑ ¿øÀÎÀ» »¡¸® ¾Ë ¼ö Àֱ⠶§¹®ÀÔ´Ï´Ù. ¶Ç´Â ¿øÀÎÀ» ¸ð¸¥´Ù ÇÏ´õ¶óµµ ¾î¶² »óȲ¿¡ ¹ö±×°¡ ¹ß»ýÇß´ÂÁö ÆľÇÇϱⰡ ½±½À´Ï´Ù. ±×·¯³ª ³×Æ®¿öÅ· ¼­¹öó·³ ÀÏ´Ü ½ÇÇàÇÑ ´ÙÀ½ ¿À·¡µµ·Ï ½ÇÇàÇÏ´Â µµÁß ¹ö±×°¡ ¹ß»ýÇÑ´Ù¸é, ¿øÀÎÀ» ¾Ë¾Æ³»±âµµ Èûµé »Ó´õ·¯, ¾î¶² »óȲ¿¡ ¹ö±×°¡ ¹ß»ýÇß´ÂÁö ¾Ë¾Æ³»±â°¡ ¸Å¿ì Èûµì´Ï´Ù. µû¶ó¼­ ÀÌ·¯ÇÑ ÇÁ·Î±×·¥ÀÏ °æ¿ì¿¡´Â ÇÁ·Î±×·¥ µ¿ÀÛ °úÁ¤À» ÆÄÀÏÀ̳ª ±âŸ ¹æ¹ýÀ» ÅëÇØ ±â·ÏÇØ µÑ ÇÊ¿ä°¡ ÀÖ½À´Ï´Ù. ÀÌ·± ±â·ÏÀ» º¸Åë log¶ó°í Çϴµ¥, ¿©±â¿¡¼­´Â ÇÁ·Î±×·¥¿¡¼­ ½±°Ô ¾µ ¼ö ÀÖ´Â ·Î±× °ü·Ã ±â´ÉÀ» ¸¸µé¾î º¸µµ·Ï ÇÏ°Ú½À´Ï´Ù. ¸ÕÀú, ¿ì¸®°¡ ¸¸µé ·Î±× ±â´ÉÀÌ °¡Á®¾ß ÇÒ °ÍµéÀº Å©°Ô ´ÙÀ½°ú °°ÀÌ »ý°¢ÇÒ ¼ö ÀÖ½À´Ï´Ù: 1. ·Î±×¸¦ ¿øÇÏÁö ¾ÊÀ» °æ¿ì, ·Î±× ±â´ÉÀ» ½±°Ô ²ø ¼ö ÀÖ¾î¾ß ÇÑ´Ù. 2. ·Î±× Á¤º¸¸¦ ÁöÁ¤ÇÑ ÆÄÀÏ¿¡ ±â·ÏÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. 3. ·Î±× Á¤º¸¸¦ ÇÊ¿äÇÏ´Ù¸é syslog(3) ÀÎÅÍÆäÀ̽º¸¦ ÅëÇؼ­ ½Ã½ºÅÛ ·Î°Å(logger)¿¡ º¸³¾ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. ù°, ·Î±× ±â´ÉÀº [xassert]()¿Í´Â ´Ù¸¨´Ï´Ù. [xassert]´Â µð¹ö±ëÇÒ ¶§°¡ ¾Æ´Ï¸é, ¸¶Ä¡ [xassert]()¸¦ ¾²Áö ¾ÊÀº °Íó·³ ¾î¶°ÇÑ ±â°è¾î Äڵ带 ¸¸µé¾î ³»Áö ¾Ê¾Æ¾ß ÇÕ´Ï´Ù. ·Î±× ±â´ÉÀº ÀÌ¿Í´Â ´Þ¸® Ç×»ó ±× ±â´ÉÀ» ¼öÇàÇÏ¿©¾ß ÇÕ´Ï´Ù. ´Ù¸¸ ¿øÇÏÁö ¾ÊÀ» °æ¿ì¿¡´Â ¾Æ¹«·± Àϵµ ÇÏÁö ¾ÊÀ» ¼ö ÀÖ´Â °ÍÀÔ´Ï´Ù. µÑ°, ·Î±× Á¤º¸´Â ÇÊ¿ä¿¡ µû¶ó¼­ ÁöÁ¤ÇÑ ÆÄÀÏ¿¡ ±â·ÏÇÒ ¼ö ÀÖ¾î¾ß ÇÕ´Ï´Ù. ÀÌ ÆÄÀÏÀº Ç×»ó µ¿ÀûÀ¸·Î º¯°æµÉ ¼ö ÀÖÀ¸¸ç, Á¤È®ÇÑ ±â·Ï ½ÃÁ¡À» À§ÇØ ÆÄÀÏ Ã³¸®¿¡ ¹öÆÛ¸¦ »ç¿ëÇÏÁö ¸»¾Æ¾ß ÇÕ´Ï´Ù. ¿ì¸®´Â Ç¥ÁØ ¶óÀ̺귯¸®¿¡¼­ Á¦°øÇÏ´Â ½ºÆ®¸² ÀÔÃâ·Â(Á¤È®È÷ FILE *¸¦ ÅëÇÏ¿©)À» ½á¼­ ÆÄÀÏ·Î ±â·ÏÇÏ°Ô ¸¸µé°Ú½À´Ï´Ù. FILE *¸¦ ¾µ °ÍÀ̹ǷΠ»óȲ¿¡ µû¶ó stdoutÀ̳ª stderr¸¦ ÅëÇÏ¿© Ç¥ÁØ Ãâ·ÂÀ̳ª Ç¥ÁØ ¿¡·¯ Ãâ·ÂÀ¸·Î Ãâ·ÂÇÒ ¼öµµ ÀÖÀ» °ÍÀÔ´Ï´Ù. ¼¼Â°, ½Ã½ºÅÛ ·Î°Å(logger)ÀÎ syslog·Î ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÏ´Â ±â´Éµµ ÀÖÀ¸¸é ³ªÁß¿¡ ´ë¸ó(daemon)°ú °°Àº ¼­¹ö ÇÁ·Î±×·¥À» ¸¸µç´Ù¸é ¸Å¿ì ¾µ¸ðÀÖÀ» °Í °°½À´Ï´Ù. ´ÜÁö syslog°¡ ¸ðµç ½Ã½ºÅÛ¿¡¼­ Áö¿øÇÏ´Â ±â´ÉÀº ¾Æ´Ï±â ¶§¹®¿¡ »óȲ¿¡ µû¶ó ¾µ ¼ö ÀÖµµ·Ï Á¶°ÇºÎ ÄÄÆÄÀÏÀ» Áö¿øÇØ¾ß ÇÒ °ÍÀÔ´Ï´Ù. ´ë°³ÀÇ °æ¿ì, °æÇè»ó, Ç×»ó ·Î±× ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÒ ¶§º¸´Ù´Â ¾î¶² Á¶°Ç¿¡ µû¶ó¼­ ·Î±× ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÒ °ÍÀÎÁö ¾Æ´ÑÁö °áÁ¤ÇÏ°í »óȲ¿¡ µû¶ó¼­ ·Î±× ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÏ´Â °æ¿ì°¡ ¸¹¾Ò½À´Ï´Ù. µû¶ó¼­ ¿ì¸®°¡ »ç¿ëÀڵ鿡°Ô Á¦°øÇÒ ÀÎÅÍÆäÀ̽º´Â ¾î¶² Á¶°Ç x°¡ ÂüÀÏ °æ¿ì¿¡ printf(3)¿Í °°Àº Çü½ÄÀ¸·Î ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÒ ¼ö ÀÖ´Â °ÍÀÔ´Ï´Ù. °á±¹ ´ÙÀ½°ú °°Àº ÀÎÅÍÆäÀ̽º¸¦ Áö´Ï°Ô µË´Ï´Ù: {{{#!vim c int message_logger(condition, const char *format, ...); }}} µÎ¹ø° ÀÌÈÄÀÇ ÀÎÀÚ´Â [xassert]()¿Í °°±â ¶§¹®¿¡ ´õ ÀÌ»ó ¼³¸íÇÒ ÇÊ¿ä´Â ¾øÀ» °ÍÀ̶ó°í »ý°¢ÇÕ´Ï´Ù. ÀÌÁ¦ ù¹ø° ÀÎÀÚ¿¡ ´ëÇؼ­ Á» ´õ »ý°¢ÇØ º¾½Ã´Ù. ¿ì¸®°¡ »ç¿ëÀÚ¿¡°Ô Á¦°øÇÏ´Â °ÍÀº ¾î¶² ¼ö½Ä(expression)ÀÌ ÂüÀ̳Ä, °ÅÁþÀÌ³Ä ÇÏ´Â °ÍÀ» ¹¯±â À§ÇÑ °ÍÀÔ´Ï´Ù. ¸¸¾à À§ÀÇ ÇÔ¼ö¿¡¼­ ¡®condition¡¯ÀÌ int ŸÀÔÀ̶ó°í °¡Á¤ÇØ º¾½Ã´Ù. ÀÌ °æ¿ì ´ÙÀ½°ú °°ÀÌ ¸í·ÉÀ» ³»¸°´Ù¸é ÄÄÆÄÀÏ·¯¿¡ µû¶ó¼­´Â ŸÀÔ º¯È¯(type conversion)¿¡ µû¸¥ °æ°í¸¦ Ãâ·ÂÇÒ ¼öµµ ÀÖ½À´Ï´Ù: {{{#!vim c message_logger(3.2, "some log message"); }}} µû¶ó¼­ conditionÀ» ¾î¶² ƯÁ¤ÇÑ Å¸ÀÔÀÇ ÆĶó¸ÞÅÍ·Î ¾²±â¿¡´Â ¹«¸®°¡ ÀÖ½À´Ï´Ù. »ý°¢Çغ» °á°ú, [xassert]()ó·³ ¸ÅÅ©·Î·Î ¾²¸é ½±°Ô ÇØ°áµÉ °Í °°½À´Ï´Ù. ±×·¡¼­ ´ÙÀ½°ú °°ÀÌ ¸¸µé¾îº¸¾Ò½À´Ï´Ù: {{{#!vim c #define MLOG(condition, ...) ((condition) ? mlog(__VA_ARGS__) : 0) }}} Áï, À§¿Í °°ÀÌ ÇÏ¸é ¡®condition¡¯¿¡ Ưº°ÇÑ Å¸ÀÔÀ» ÁöÁ¤ÇÑ °ÍÀÌ ¾Æ´Ï±â ¶§¹®¿¡ ÄÄÆÄÀÏ·¯°¡ °æ°í¸¦ ÁÖ´Â °æ¿ì´Â ¾øÀ» °Í °°½À´Ï´Ù. ¿©±â¿¡¼­ mlog()´Â ´Ü¼øÈ÷ printf(3)¿Í °°Àº ÆĶó¸ÞÅ͸¦ ¹Þ½À´Ï´Ù. == Stream Buffer == mlog() ÇÔ¼ö´Â Á¶±Ý À̵û°¡ ¸¸µé¾î º¸±â·Î ÇÏ°í, ÀÌ ¸ðµâÀÌ Á¦°øÇØ¾ß ÇÒ °ÍµéÀ» Á» ´õ »ý°¢ÇØ º¸±â·Î ÇսôÙ. ÀÏ´Ü »ç¿ëÀÚ°¡ Ưº°È÷ ÁöÁ¤ÇÏÁö ¾Ê¾Ò´Ù¸é ·Î±×´Â ÁöÁ¤ÇÑ ½ºÆ®¸²À¸·Î Ãâ·ÂµÇ°Ô ÇսôÙ. ÀÌ·¸°Ô Çϱâ À§ÇÏ¿©, ´ÙÀ½°ú °°ÀÌ ·Î±×¿ë ½ºÆ®¸²À» °¡Áö°í ÀÖ´Â °Ô ÁÁÀ» °Í °°½À´Ï´Ù: {{{#!vim c static FILE *mlog_stream; }}} ±×·¡¼­ ¡®mlog_stream¡¯ÀÌ ³Î(null)ÀÎ °æ¿ì¿¡ ·Î±×¸¦ Ãâ·ÂÇÏÁö ¾Êµµ·Ï ¸¸µé °ÍÀÔ´Ï´Ù. ±×¸®°í ÀÌ ¡®mlog_stream¡¯¿¡ ½ºÆ®¸²À» ÁöÁ¤ÇÒ ¼ö ÀÖ´Â ÇÔ¼ö¿Í ÁöÁ¤µÈ ½ºÆ®¸²À» ¾ò¾î ³¾ ¼ö ÀÖ´Â ÇÔ¼ö¸¦ ´ÙÀ½°ú °°ÀÌ ¸¸µé¾ú½À´Ï´Ù: {{{#!vim c FILE * mlog_get_stream(void) { return mlog_stream; } int mlog_set_stream(FILE *fp) { fflush(fp); if (setvbuf(fp, 0, _IONBF, 0) != 0) return -1; mlog_stream = fp; return 0; } }}} mlog_get_stream()Àº ¼³¸íÇÒ ÇÊ¿äµµ ¾ø´Â °£´ÜÇÑ ÇÔ¼öÀÔ´Ï´Ù. mlog_set_stream()ÀÇ °æ¿ì, setvbuf(3)¸¦ ºÎ¸£´Â °ÍÀ» »©³õ°í´Â ´Ü¼øÈ÷ ¡®mlog_stream¡¯¿¡ ÁÖ¾îÁø ÀÎÀÚ¸¦ ´ëÀÔÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. ¿©±â¿¡¼­ setvbuf()°¡ ÇÏ´Â ÀÏÀº ÁÖ¾îÁø ½ºÆ®¸²¿¡ ´ëÇÑ ³»ºÎ ¹öÆÛ¸¦ ¼³Á¤ÇÏ´Â °ÍÀÔ´Ï´Ù. ¿©·¯ºÐÀº Ç¥ÁØ ÀÔ·Â ½ºÆ®¸², ¡®stdin¡¯°ú Ç¥ÁØ Ãâ·Â ½ºÆ®¸² ¡®stdout¡¯, ±×¸®°í Ç¥ÁØ ¿¡·¯ Ãâ·Â ½ºÆ®¸²ÀÎ ¡®stderr¡¯¸¦ ÀÌ¹Ì ¾Ë°í ÀÖÀ» °ÍÀÔ´Ï´Ù. ±×·±µ¥ ¡®stdout¡¯°ú ¡®stderr¡¯ÀÇ Â÷ÀÌÁ¡À» ¸ð¸£´Â ºÐµµ Àֱ⠶§¹®¿¡ Àá±ñ ±× Â÷ÀÌÁ¡¿¡ ´ëÇØ ´Ù·ç°Ú½À´Ï´Ù. ½ºÆ®¸² ŸÀÔ, Á¤È®È÷ ¸»ÇØ FILE * ŸÀÔÀ¸·Î ¿¬°áµÈ ÆÄÀÏÀº Ç¥ÁØ C ¶óÀ̺귯¸®°¡ ³»ºÎÀûÀ¸·Î ¹öÆÛ¸¦ °¡Áö°í ÀÖ½À´Ï´Ù. µû¶ó¼­ ¿©·¯ºÐÀÌ fprintf(3), fputs(3), fputc(3), ¶Ç´Â fwrite(3) µîÀ¸·Î ÆÄÀÏ¿¡ ¾´´Ù(write) ÇÏ´õ¶óµµ ¹Ù·Î ½áÁöÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. ´ë°³ÀÇ °æ¿ì, ¾î´À Å©±â±îÁö´Â ¹öÆÛ¿¡ ¾²°Ô µÇ°í, ÀÌ ¹öÆÛ°¡ ´Ù Â÷°Å³ª ¶Ç´Â ¾î¶² Ư¼öÇÑ »óȲÀÌ ¹ß»ýÇÒ °æ¿ì, ½ÇÁ¦ ÆÄÀÏ¿¡ ¾²°Ô µË´Ï´Ù. Ưº°È÷ ÁöÁ¤ÇÏÁö ¾ÊÀº ÇÑ, ¡®stdout¡¯°ú ¡®stderr¡¯´Â ¶È°°ÀÌ Å͹̳ÎÀÇ Ãâ·ÂÀ¸·Î ÁöÁ¤µÇ¾î ÀÖÁö¸¸, ¡®stdout¡¯ÀÇ °æ¿ì, ¹öÆÛ¸µ(buffering)À» ÇÏÁö¸¸, ¡®stderr¡¯´Â ¹öÆÛ¸µÀ» ÇÏÁö ¾Ê°í ¹Ù·Î Ãâ·ÂÇÏ°Ô µË´Ï´Ù. ¾Æ±î ¹öÆÛ°¡ ´Ù Â÷Áö ¾Ê¾Æµµ ¾î¶² Ư¼öÇÑ »óȲÀÌ ¹ß»ýÇÏ¸é ½ÇÁ¦ ÆÄÀÏ¿¡ ¾´´Ù°í Çß½À´Ï´Ù. º¸ÅëÀº newline ¹®ÀÚÀÎ ¡®\n¡¯À» Ãâ·ÂÇÏ¸é ¹öÆÛÀÇ ³»¿ëÀ» Ãâ·ÂÇÏ°Ô µË´Ï´Ù. ´ÙÀ½ ÇÁ·Î±×·¥À» ½ÇÇàÇÏ¸é ±× Â÷À̸¦ ½±°Ô ¾Ë ¼ö ÀÖ½À´Ï´Ù: {{{#!vim c #include int main(void) { fprintf(stdout, "hello"); fprintf(stderr, "hi"); fprintf(stdout, ", world!\n"); return 0; } }}} À§ ÇÁ·Î±×·¥(tmp.c)À» Á¦ ½Ã½ºÅÛ¿¡¼­ ÄÄÆÄÀÏÇÏ°í ½ÇÇàÇÑ °á°ú´Â ´ÙÀ½°ú °°½À´Ï´Ù: {{{ $ gcc tmp.c $ ./a.out hihello, world! $ _ }}} Ãâ·ÂÀº ¡°hello¡±¸¦ ¸ÕÀú ÇßÁö¸¸, ¡®stdout¡¯À¸·Î Ãâ·ÂµÇ¾î ¹öÆÛ¿¡ ´ë±âÇØ ÀÖ´Â »óÅÂÀÔ´Ï´Ù. ÀÌ ¶§ ¹öÆÛ¸µµÇÁö ¾Ê´Â ¡®stderr¡¯·Î ¡°hi¡±¸¦ Ãâ·ÂÇÏ¸é ¹Ù·Î Ãâ·ÂµÇ°í, ´ÙÀ½À¸·Î ¡®stdout¡¯À¸·Î ¡°, world!\n¡±¸¦ Ãâ·ÂÇϸé, ¾Æ±î ´ë±âÇÏ°í ÀÖ´ø ¡°hello¡±¿Í ÇÔ²² Ãâ·ÂµÇ¾î, ½ÇÁ¦ Å͹̳ηδ ¡°hihello, world!¡±°¡ Ãâ·ÂµË´Ï´Ù. == syslog(3) Interface == syslog1´Â ½Ã½ºÅÛ ·Î±× ¸Þ½ÃÁö¸¦ ±â·ÏÇÏ´Â ÀÎÅÍÆäÀ̽ºÀÔ´Ï´Ù. ÀϹÝÀûÀ¸·Î ½Ã½ºÅÛ¿¡´Â syslogd(8) µ¥¸ó ÇÁ·Î¼¼½º°¡ Á¸ÀçÇϸç, ¸ðµç syslog ·Î±×µéÀ» ¸ð¾Æ, ÁöÁ¤ÇÑ °÷¿¡ Ãâ·Â ¶Ç´Â ÀúÀåÇÏ°Ô µË´Ï´Ù. µû¶ó¼­ syslog(3)À¸·Î Ãâ·ÂÇÑ´Ù´Â °ÍÀº °á±¹ syslogd(8)¿¡ ¸Þ½ÃÁö¸¦ º¸³»°í, syslogd(8) ÇÁ·Î¼¼½º°¡ Á¤ÇØÁø ±ÔÄ¢¿¡ µû¶ó ·Î±×¸¦ ó¸®ÇÕ´Ï´Ù. syslogd(8)·Î ¸Þ½ÃÁö¸¦ º¸³»±â À§ÇØ, ´ë°³ÀÇ ½Ã½ºÅÛ¿¡¼­´Â ¾Æ·¡ ÇÔ¼öµéÀ» Á¦°øÇÕ´Ï´Ù: {{{#!vim c #include void openlog(const char *ident, int option, int facility); void syslog(int priority, const char *format, ...); void closelog(void); #include void vsyslog(int priority, const char *format, va_list ap); }}} ÀÏ´Ü syslog(3)´Â printf(3)¿Í ºñ½ÁÇÑ ÀÎÅÍÆäÀ̽º¸¦ Á¦°øÇϸç, ¸¶Áö¸· vsyslog(3)ÀÇ °æ¿ì, vprintf(3)¿Í À¯»çÇÑ ÀÎÅÍÆäÀ̽º¸¦ Á¦°øÇÕ´Ï´Ù. ½Ã½ºÅÛ¿¡ µû¶ó¼­ vsyslog(3)¸¦ Á¦°øÇÏÁö ¾Ê´Â °æ¿ìµµ ÀÖ½À´Ï´Ù. ÀÏ´Ü syslog(3)·Î ¸Þ½ÃÁö¸¦ Ãâ·ÂÇϱâ Àü¿¡ openlog(3)¸¦ ºÒ·¯¼­ ÃʱâÈ­ÇØ¾ß Çϸç, ¸ðµç ·Î±×¸¦ ´Ù Ãâ·ÂÇÑ ÈÄ¿¡´Â closelog(3)·Î Á¾·áÇÕ´Ï´Ù. ÀÚ¼¼ÇÑ »çÇ×Àº ¸Å´º¾ó ÆäÀÌÁö¸¦ Âü°íÇϱ⠹ٶø´Ï´Ù. == mlog() == ´Ù½Ã º»·ÐÀ¸·Î µ¹¾Æ¿Í¼­, ÀÌÁ¦ mlog()¸¦ ¸¸µé¾î º¸°Ú½À´Ï´Ù. ¸ÕÀú, mlog()ÀÇ Ãâ·ÂÀº ´ÙÀ½ ²Ã·Î Ãâ·ÂµÉ °ÍÀÔ´Ï´Ù: {{{½Ã°£: ÇÁ·Î±×·¥À̸§ [PID]: ¸Þ½ÃÁö}}} ½Ã°£À» Ãâ·ÂÇϱâ À§ÇØ, ¿ì¸®´Â time(2), localtime(3), strftime(3)À» ¾²·Á°í ÇÕ´Ï´Ù. ÇÁ·Î±×·¥ À̸§Àº Àü¿ª º¯¼ö ¡®program_name¡¯¿¡ ÀúÀåµÇ¾î ÀÖ´Ù°í °¡Á¤ÇÏ°Ú½À´Ï´Ù. ÇÁ·Î¼¼½º id(pid)´Â getpid(2)¸¦ ½á¼­ ¾òÀ¸·Á°í ÇÕ´Ï´Ù. ½Ã°£À» ¾ò¾î³»´Â ÇÔ¼ö´Â ´ÙÀ½°ú °°ÀÌ ¸¸µé°Ú½À´Ï´Ù: {{{#!vim c static const char *current_time(void); }}} mlog()´Â ½ºÆ®¸²°ú syslog(3) ÀÎÅÍÆäÀ̽º µÑ Áß Çϳª·Î Ãâ·ÂÀ» Çϱ⠶§¹®¿¡, ¾î´À ÂÊÀ¸·Î Ãâ·ÂÀ» ÇÒ Áö Á¤Ã¥(policy)À» °áÁ¤ÇØ¾ß ÇÕ´Ï´Ù. ´ÙÀ½°ú °°ÀÌ using_stream()À» ¸¸µé¾î¼­ ÀÌ ÇÔ¼ö°¡ ÂüÀ» ¸®ÅÏÇÏ¸é ½ºÆ®¸²À¸·Î Ãâ·ÂÇϵµ·Ï ÇÏ°Ú½À´Ï´Ù. {{{#!vim c static int using_stream(void); }}} À§ µÎ ÇÔ¼ö¸¦ ÀÌ¹Ì ¸¸µé¾ú´Ù°í °¡Á¤ÇÏ°í, syslog(3) ÀÎÅÍÆäÀ̽ºµµ ÃʱâÈ­µÇ¾î ÀÖ´Ù°í °¡Á¤ÇÏ°í, mlog()¸¦ ¸¸µé¾î º¾½Ã´Ù. ¾îÂ÷ÇÇ printf(3)¿Í ºñ½ÁÇÑ ÀÏÀ» Çϱ⠶§¹®¿¡, ¾Õ¿¡¼­ ¸¸µç ASSERT()¿Í ¸Å¿ì ºñ½ÁÇÕ´Ï´Ù. ¸ÕÀú Àüü mlog()ÀÇ »À´ë´Â ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim c void mlog(const char *format, ...) { if (using_stream()) { /* ½ºÆ®¸²À¸·Î Ãâ·Â */ } else { /* syslog·Î Ãâ·Â */ } } }}} ÀÌ ÀýÀÇ ¾Õ¿¡¼­ ¿ì¸®´Â ÀÌ¹Ì ·Î±×ÀÇ Æ÷¸ËÀ» Á¤Çß½À´Ï´Ù. syslogd(8)´Â ¾Ë¾Æ¼­ ¸Þ½ÃÁö¸¦ Æ÷¸Ë½ÃÄÑ ÁֹǷÎ, ¿ì¸®´Â ½ºÆ®¸²À¸·Î Ãâ·ÂÇÒ °æ¿ì¿¡¸¸ Æ÷¸ËÇØÁÖ¸é µË´Ï´Ù. µû¶ó¼­ À§ »À´ë¿¡¼­ using_stream()ÀÌ ÂüÀÎ °æ¿ì¿¡ ´ÙÀ½°ú °°Àº Äڵ带 ½ÇÇàÇÕ´Ï´Ù. {{{#!vim c va_list ap; fprintf(mlog_stream, "%s: %s[%d]: ", current_time(), program_name, (int)getpid()); va_start(ap, format); vfprintf(mlog_stream, format, ap); va_end(ap); fputc('\n', mlog_stream); }}} syslogd(8)·Î ¸Þ½ÃÁö¸¦ º¸³¾ °æ¿ì (Áï, using_stream()ÀÌ °ÅÁþÀ» ¸®ÅÏÇÒ °æ¿ì)¸¦ »ý°¢ÇØ º¾½Ã´Ù. ¸ÕÀú vsyslog()°¡ Á¦°øµÇÁö ¾Ê´Â´Ù¸é, ¿ì¸®´Â mlog()ÀÇ °¡º¯ ÀÎÀÚ ºÎºÐÀ» syslog(3)·Î ÀüÇØÁÙ ¹æ¹ýÀÌ ¾ø½À´Ï´Ù. µû¶ó¼­ ÇϳªÀÇ ¹öÆÛ¸¦ ¸¸µé¾î¼­ ¿©±â¿¡´Ù ·Î±× ¸Þ½ÃÁö¸¦ Æ÷¸ÅÆÃÇÏ¿© ÀúÀåÇÑ ´ÙÀ½, ÀÌ ¹öÆÛ¸¦ syslog(3)¿¡ Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. À̸¦ À§Çؼ­ ¿ì¸®´Â ¹öÆÛ¸¦ ÁغñÇØ¾ß Çϸç, ¹öÆÛ¿¡ Æ÷¸ÅÆÃÇÑ ¸Þ½ÃÁö¸¦ ÀúÀåÇϱâ À§Çؼ­ vsnprintf(3)¸¦ ½á¾ß ÇÕ´Ï´Ù. {{{#!vim c #define MLOG_BUFFER_MAX 1024 static char mlog_buffer[MLOG_BUFFER_MAX]; }}} ¶ÇÇÑ vsyslog()°¡ Á¦°øµÇÁö ¾Ê´Â °æ¿ì¿Í Á¦°øµÇ´Â °æ¿ì¸¦ ±¸º°Çϱâ À§ÇØ, ¿ì¸®´Â HAVE_VSYSLOG¶ó´Â ¸ÅÅ©·Î¸¦ µÎ°í Á¦°øµÇ´Â °æ¿ì¿¡¸¸ ÀÌ ¸ÅÅ©·Î¸¦ Á¤ÀÇÇÒ °ÍÀÔ´Ï´Ù. ±× °á°ú ½ÇÁ¦ ÄÚµå ºÎºÐÀº ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim c int ret; va_list ap; #ifdef HAVE_VSYSLOG vsyslog(LOG_INFO | LOG_USER, format, ap); #else va_start(ap, format); ret = vsnprintf(mlog_buffer, MLOG_BUFFER_MAX, format, ap); va_end(ap); if (ret >= MLOG_BUFFER_MAX || ret < 0) mlog_buffer[MLOG_BUFFER_MAX - 1] = '\0'; syslog(LOG_INFO | LOG_USER, "%s", mlog_buffer); #endif /* HAVE_VSYSLOG */ }}} vsprintf(3)¸¦ ¾²Áö ¾Ê°í, Á¶±Ý ´õ º¹ÀâÇÑ vsnprintf(3)¸¦ ¾´ ÀÌÀ¯´Â °£´ÜÇÕ´Ï´Ù. ÁÖ¾îÁø ¹öÆÛ, mlog_buffer°¡ ¿À¹öÇ÷ο찡 ÀϾ °æ¿ì ¹ß»ýÇÒ ¼ö ÀÖ´Â ¿Àµ¿ÀÛÀ» ¸·±â À§Çؼ­ÀÔ´Ï´Ù. À§ Äڵ忡¼­ va_end()¸¦ ºÎ¸¥ ´ÙÀ½ÀÇ ¡®if¡¯´Â ÀÌ ¿À¹öÇ÷ο찡 ÀϾ´ÂÁö °Ë»çÇÏ´Â ºÎºÐÀÔ´Ï´Ù. Áï, vsnprintf()ÀÇ ¸®ÅÏ°ªÀÌ ¾ç¼öÀÌ°í, MLOG_BUFFER_MAXº¸´Ù ÀÛÀ¸¸é, mlog_buffer¿¡ ¿¡·¯¾øÀÌ Æ÷¸ÅÆõǾú´Ù°í ÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÏ´Ü ¸Þ½ÃÁö°¡ mlog_buffer¿¡ ÀúÀåµÇ¾úÀ¸¸é, syslog(3)·Î º¸³À´Ï´Ù. HAVE_VSYSLOG°¡ Á¤ÀÇµÈ °æ¿ìµ¥´Â °£´ÜÇÏ°Ô vsyslog()¸¦ ÅëÇØ ¸Þ½ÃÁö¸¦ Àü´ÞÇÕ´Ï´Ù. mlog()¿¡ ´ëÇÑ ¿ÏÀüÇÑ ÄÚµå´Â ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim c #define MLOG_BUFFER_MAX 1024 static char mlog_buffer[MLOG_BUFFER_MAX]; void mlog(const char *format, ...) { va_list ap; int ret; if (using_stream()) { fprintf(mlog_stream, "%s: %s[%d]: ", current_time(), program_name, (int)getpid()); va_start(ap, format); vfprintf(mlog_stream, format, ap); va_end(ap); fputc('\n', mlog_stream); } else { #ifdef HAVE_VSYSLOG vsyslog(LOG_INFO | LOG_USER, format, ap); #else va_start(ap, format); ret = vsnprintf(mlog_buffer, MLOG_BUFFER_MAX, format, ap); va_end(ap); if (ret >= MLOG_BUFFER_MAX || ret < 0) mlog_buffer[MLOG_BUFFER_MAX - 1] = '\0'; syslog(LOG_INFO | LOG_USER, "%s", mlog_buffer); #endif /* HAVE_VSYSLOG */ } } }}} ---- == mlog.h == {{{#!vim c /* $Id: mlog,v 1.6 2008/04/10 09:26:22 kss Exp kss $ */ /* * stream/syslog logger module * Copyright (C) 2003, 2004 Seong-Kook Shin */ #ifndef MLOG_H_ #define MLOG_H_ #include #ifdef HAVE_CONFIG_H # include #endif /* This indirect writing of extern "C" { ... } makes Emacs happy */ #ifndef BEGIN_C_DECLS # ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } # else # define BEGIN_C_DECLS # define END_C_DECLS # endif #endif /* BEGIN_C_DECLS */ BEGIN_C_DECLS #define MLOG_BUFFER_MAX 4096 /* You should define PROGRAM_NAME somewhere in your code. */ extern const char *program_name; /* Set the stream for logging. * Returns zero on success, otherwise returns -1 */ extern int mlog_set_stream(FILE *fp); /* Get the stream for logging. */ extern FILE *mlog_get_stream(void); extern void mlog(const char *format, ...); #define MLOG(expr, ...) do { if (expr) mlog(__VA_ARGS__); } while (0) END_C_DECLS }}} ---- == mlog.c == {{{#!vim c #include #include #include #include #define TIME_BUF_MAX 32 static FILE *mlog_stream = 0; static int syslog_opened = 0; #ifndef HAVE_VSYSLOG static char mlog_buffer[MLOG_BUFFER_MAX]; #endif static int using_stream(void) { if (mlog_stream) return 1; if (!syslog_opened) { openlog(program_name, LOG_CONS | LOG_NOWAIT | LOG_PID, LOG_USER); atexit(closelog); syslog_opened = 1; } return 0; } int mlog_set_stream(FILE *fp) { fflush(fp); if (setvbuf(fp, 0, _IONBF, 0) != 0) { /* Warning: cannot empty the stream buffer. */ return -1; } mlog_stream = fp; return 0; } FILE * mlog_get_stream(void) { return mlog_stream; } static const char * current_time() { struct tm *tmptr; time_t t; static char buf[TIME_BUF_MAX]; int ret; t = time(0); tmptr = localtime(&t); ret = strftime(buf, TIME_BUF_MAX, "%b %d %H:%M:%S", tmptr); if (ret == TIME_BUF_MAX || ret == 0) return 0; return buf; } void mlog(const char *format, ...) { va_list ap; int ret; if (using_stream()) { fprintf(mlog_stream, "%s: %s[%d]: ", current_time(), program_name, (int)getpid()); va_start(ap, format); vfprintf(mlog_stream, format, ap); va_end(ap); fputc('\n', mlog_stream); } else { #ifdef HAVE_VSYSLOG vsyslog(LOG_INFO | LOG_USER, format, ap); #else va_start(ap, format); ret = vsnprintf(mlog_buffer, MLOG_BUFFER_MAX, format, ap); va_end(ap); if (ret >= MLOG_BUFFER_MAX || ret < 0) mlog_buffer[MLOG_BUFFER_MAX - 1] = '\0'; syslog(LOG_INFO | LOG_USER, "%s", mlog_buffer); #endif /* HAVE_VSYSLOG */ } } #ifdef MLOG_TEST const char *program_name = "mlog"; int main(int argc, char *argv[]) { FILE *fp; char buf[10]; fp = fopen(argv[1], "a"); if (!fp) return -1; mlog_set_stream(fp); MLOG(1, "hello, %s", "world"); gets(buf); MLOG(1, "hello, %s", "world"); gets(buf); MLOG(1, "hello, %s", "world"); gets(buf); fclose(fp); return 0; } #endif /* MLOG_TEST */ }}} ---- Please see CCodeSnippets == TODO ==