ÃÖÁøÈñ <jhchoi@os.korea.ac.kr> ¿ª.
2001³â 4¿ù 20ÀÏ
ÀÌ ¹®¼ÀÇ ¸ñÀûÀº FreeBSD ȯ°æ¿¡¼ KLD¸¦ °³¹ßÇϰí À̸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹ÖÀÇ ±âº» Áö½ÄÀ» ¼Ò°³ÇÏ ´Â µ¥ ÀÖ½À´Ï´Ù. µû¶ó¼ ¿¹Á¦¸¦ Áß½ÉÀ¸·Î(learn by example) Â÷±ÙÂ÷±Ù ÁøÇàÇØ ³ª°¡¸é¼ µ¶ÀÚ°¡ ÃÖ´ëÇÑ ½±°Ô KLD Äڵ带 ÀÛ¼ºÇÒ ¼ö ÀÖµµ·Ï ÀÏÁ¾ÀÇ »À´ë ÄÚµå(skeleton code)µµ Á¦°øÇÏ´Â ½ÄÀ¸·Î ±ÛÀ» Àü°³ÇØ ³ª°¥ °ÍÀÔ´Ï´Ù. [µ¿Àû Ä¿³Î ¸µÄ¿(dynamic kernel linker)¿¡ Àͼ÷Ä¡ ¾ÊÀº µ¶ÀÚµéÀ» À§ÇØ Àá±ñ ¼³¸íÇÏÀÚ¸é KLD´Â FreeBSD 3.1¿¡ ÀÖ¾ú´ø LKM(Loadable Kernel Modules)À» ´ëüÇÑ ÀÎÅÍÆäÀ̽º·Î, µÑÀº ¸ðµÎ ½Ã½ºÅÛ °ü ¸®ÀÚ°¡ ¼öÇà ÁßÀÎ ½Ã½ºÅÛ¿¡ µ¿ÀûÀ¸·Î ¾î¶² ±â´ÉÀ» Ãß°¡/»èÁ¦ÇÒ ¼ö ÀÖ´Â ±â´ÉÀ» Á¦°øÇÕ´Ï´Ù. ÀÌ·¯ÇÑ Æ¯Â¡À» ÀÌ¿ëÇÏ¸é ¼ÒÇÁÆ®¿þ¾î °³¹ßÀÚµéÀº ÀÛ¼ºÇÑ Ä¿³Î ÄÚµåÀÇ Å×½ºÆ®Çϱâ À§ÇØ ½Ã½ºÅÛÀ» ÀçºÎÆÃ ÇÒ Çʿ䰡 ¾ø°Ô µË´Ï´Ù[ref. 1]. ´ëÇ¥ÀûÀÎ ¿¹·Î µð¹ÙÀ̽º µå¶óÀ̹ö, ƯÈ÷ ³×Æ®¿öÅ© Ä«µå¸¦ À§ÇÑ µå¶óÀ̹ö ¸¦ °³¹ßÇÏ´Â »óȲÀ» µé ¼ö ÀÖ½À´Ï´Ù. ÇÑ °¡Áö ¾Ë¾ÆµÎ¾î¾ß ÇÒ Á¡Àº KLD°¡ LKMÀÇ ºÎºÐ ÁýÇÕÀ̶ó´Â °ÍÀÔ ´Ï´Ù. Áï, KLD¶ó´Â ¿ë¾î´Â Ä¿³Î ¸ðµâ ½Ã½ºÅÛÀÌ ±âÁ¸°ú ´Þ¶óÁ³´Ù´Â »ç½ÇÀ» ºÎ°¢½Ã۱â À§ÇØ ¼±ÅÃµÈ ¿ë¾î¶ó´Â ¶æÀÌÁÒ. Á» ´õ ÀÌÇØ¸¦ µ½±â À§ÇØ ¿©±â¼ Peter WemmÀÇ ±ÛÀ» ÀοëÇϰڽÀ´Ï´Ù. (IRC¿¡¼ ÀÖ¾ú´ø "FreeBSD KLD vs LKM"À̶ó´Â ²Ï ½Éµµ ±í¾ú´ø ³íÀÇ¿¡¼ ¹ßÃéÇÕ´Ï´Ù.) LKM ½Ã½ºÅÛÀº Àç¹èÄ¡µÈ ¹ÙÀ̳ʸ® µ¥ÀÌÅ͸¦ »ç¿ëÀÚ ·¹º§ÀÇ ¸µÄ¿¸¦ »ç¿ëÇÏ¿© Ä¿³Î°ú °áÇÕ½Ãŵ´Ï´Ù. - KLD ½Ã½ºÅÛÀº Ä¿³Î ³»ºÎ¿¡¼ Àç¹èÄ¡°¡ ÀÌ·ç¾î Áý´Ï´Ù. ¹Ý¸é, LKMÀº Ä¿³Î°ú LKM ÇÁ·Î±×·¥À» ¿¬°áÇØ ÁÖ´Â ¾î¶² Ưº°ÇÑ ÀÚ·á ±¸Á¶°¡ ÇÊ¿äÇϸç, lkm µå¶óÀ̹ö°¡ ÀÌ ÀÚ·á ±¸Á¶ÀÇ ³»¿ëÀ» ¾Ë°í ÀÖ¾î¾ß ÇÕ´Ï´Ù. °¡·É, VFS lkmÀ̶ó¸é vfs Å×À̺íÀ» °¡¸®Å°´Â ÀÚ·á ±¸Á¶¸¦ À¯ÁöÇϰí ÀÖ¾î¾ß ÇÑ´Ù´Â ¸»ÀÔ´Ï´Ù. - LKMÀº ÇϳªÀÇ ¿ëµµ¿¡ »ç¿ëÇϱâ À§ÇØ ¼³°èµÇ¾úÀ¸¸ç, LKM Äڵ带 ½ÇÁ¦ Ä¿³Î ÄÚµå·Î º¯È½ÃŰ´Â °Íµµ ¸Å¿ì ¾î·Á¿î ÀÛ¾÷ÀÔ´Ï´Ù. - KLD´Â ¿©·¯ ¿ëµµ¸¦ ¸¸Á·½Ãų ¼ö ÀÖ´Â º¸´Ù º¸ÆíÀûÀÎ ±¸Á¶¸¦ ÁöÇâÇÕ´Ï´Ù. ÀÌ·± ÀÌÀ¯·Î ÇϳªÀÇ ÆÄÀÏÀÌ 0°³ ÀÌ»óÀÇ ¸ðµâÀ» Æ÷ÇÔÇÒ ¼ö ÀÖ½À´Ï´Ù. - °¢ ¸ðµâ ³»ºÎ¿¡´Â ÀÚ½ÅÀ» ÃʱâÈÇÏ°í µî·Ï½ÃŰ´Â ¸ÅÄ¿´ÏÁòÀÌ Æ÷ÇԵǾî ÀÖ½À´Ï´Ù. - KLD¿Í Ä¿³Î ÄÚµå´Â °°Àº ½Ã±â¿¡ ÄÄÆÄÀϵ˴ϴÙ. - Ä¿³Î ÄÚµåÀÇ ÀϺθ¦ ½±°Ô KLD·Î ¹Ù²Ü ¼ö ÀÖ½À´Ï´Ù. - °¢ ¸ðµâ »çÀÌÀÇ ÀÇÁ¸¼º°ú ¹öÁ¯ °ü¸®´Â ¸ðµâ ·¹º§¿¡¼ ÀÌ·ç¾î Áý´Ï´Ù. ÀÌ Æ©Å丮¾óÀÌ KLD ÄÚµå ÀÛ¼º¹ýÀÇ ±âÃʸ¦ ¹è¿ì°í ½ÍÀº »ç¶÷µéÀ» ´ë»óÀ¸·Î ÀÛ¼ºµÇ¾ú´Ù´Â »ç½Ç¿¡ ´Ù½Ã Çѹø ÁÖ¸ñÇØ ÁֽʽÿÀ. µû¶ó¼ ÀÌ ¹®¼¸¦ Á¦´ë·Î ÀÌÇØÇÏ·Á¸é FreeBSD Ä¿³Î¿¡ ´ëÇÑ Áö½ÄÀÌ ¾î´À Á¤µµ´Â ÀÖ¾î¾ß Çϸç, C ÇÁ·Î±×·¥µµ ¾î´À Á¤µµ´Â ÀÛ¼ºÇÒ ¼ö ÀÖ¾î¾ß ÇÕ´Ï´Ù. ¸¶Áö¸·À¸·Î ÀÌ ¹®¼ÀÇ ¸ðµç ¿¹Á¦°¡ FreeBSD 4.0¿¡¼ ÀÛ¼ºµÇ¾ú´Ù´Â »ç½Ç¿¡ À¯ÀÇÇϽʽÿÀ. ÀÌ ¹®¼¿¡¼´Â ´ÙÀ½°ú °°Àº ÁÖÁ¦¸¦ ´Ù·ì´Ï´Ù. - ¸ðµç KLD ÇÁ·Î±×·¥ÀÇ ÀϹÝÀû Ư¼º - KLD ½Ã½ºÅÛ ÄÝÀÇ »À´ë ÄÚµå - KLD ij¸¯ÅÍ µð¹ÙÀ̽º µå¶óÀ̹ö(character device driver)ÀÇ »À´ë ÄÚµå ÀÌ ¹®¼ÀÇ Ã¹¹øÂ° ¸ñÀûÀº KLD¿¡ Àͼ÷ÇÑ »ç¶÷µéÀÌ °£´ÜÇÑ KLD ÇÁ·Î±×·¥À» ÀÛ¼ºÇÒ ¼ö ÀÖµµ·Ï µµ¿Í ÁÖ´Â °ÍÀ̸ç, KLD ÀÛ¼ºÀ» ÅëÇØ KLD¿¡ ´ëÇØ º¸´Ù ±íÀº ÀÌÇØ¸¦ ÇÏ¿© À̸¦ °í±Þ ¼öÁØÀÇ ÀÛ¾÷¿¡ Ȱ¿ëÇϵµ·Ï ÇÏ ´Â °ÍÀÌ µÎ¹øÂ° ¸ñÀûÀÔ´Ï´Ù.
Characteristics common to all KLDs
¸ðµç KLD ÇÁ·Î±×·¥¿¡ ¹Ýµå½Ã Æ÷ÇԵǾî¾ß ÇÏ´Â µÎ°³ÀÇ ÁÖ¿ä ÇÔ¼ö/¸ÅÅ©·Î°¡ Àִµ¥, ¹Ù·Î ´ÙÀ½°ú °°½À´Ï
´Ù.
- ·Îµå Çڵ鷯 ÇÔ¼ö(Load Handler Function)
- DECLARE_MODULE ¸ÅÅ©·Î (Macro)
- MakefileÀ» ÀÌ¿ëÇÑ ¼Õ½¬¿î ÄÄÆÄÀÏ
±âº»ÀûÀ¸·Î ·Îµå Çڵ鷯 ÇÔ¼ö´Â ¾î¶² KLD ÇÁ·Î±×·¥À» ·ÎµåÇÏ°í ¾ð·Îµå(unload)ÇÏ´Â ¿ªÇÒÀ» ´ã´çÇϰí
ÀÖ½À´Ï´Ù. °£´ÜÇÑ ·Îµå Çڵ鷯 Äڵ带 º¸¸é¼ À̾߱⸦ ÁøÇàÇϰڽÀ´Ï´Ù.
static int
load_handler(module_t mod, int what, void* arg)
{
int err = 0;
switch(what){
case MOD_LOAD:
uprintf("KLD loaded successfully!\n");
break;
case MOD_UNLOAD:
uprintf("KLD unloaded successfully!\n");
break;
default:
err = EINVAL;
break;
}
return (err);
}
ÀÌ ·Îµå Çڵ鷯(load handler)´Â /usr/include/sys/module.h¿¡ Á¤ÀÇµÈ ÇÔ¼ö Æ÷ÀÎÅÍ¿¡ ´ëÀÀµË´Ï´Ù.
typedef int (*modeventhand_t)(module_t mod, int what, void* arg);
'module_t mod' ±¸Á¶Ã¼´Â ¸ðµâ ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅÍÀÔ´Ï´Ù. ÀÌ ±¸Á¶Ã¼´Â ÇöÀç ·ÎµåµÈ ¸ðµâµéÀÇ ¿¬°á ¸®
½ºÆ®ÀÇ ÀϺÎÀÔ´Ï´Ù. µû¶ó¼ ·ÎµåµÈ ´Ù¸¥ ¸ðµâµé°ú ¿¬°áµÇ¸ç, KLD Id ¹øÈ£ µîÀÇ À¯¿ëÇÑ ´Ù¸¥ Á¤º¸µéµµ Æ÷
ÇÔÇϰí ÀÖ½À´Ï´Ù.
'int what'Àº modeventtype_t¿¡ µû¶ó °¢°¢ ´ÙÀ½°ú °°Àº °ªµé Áß Çϳª°¡ µË´Ï´Ù.
MOD_LOAD : ¸ðµâÀÌ ·ÎµåµÉ ¶§ ¼³Á¤ÇÕ´Ï´Ù. (kldload)
MOD_UNLOAD : ¸ðµâÀÌ ¾ð·Îµå(unload)µÉ ¶§ ¼³Á¤µË´Ï´Ù. (kldunload)
MOD_SHUTDOWN : ¸ðµâÀÌ ¿ÏÀüÈ÷ Á¦°ÅµÉ ¶§ ¼³Á¤µË´Ï´Ù.
DECLARE_MODULE ¸ÅÅ©·Î ¿ª½Ã ¸ðµç KLD¿¡¼ »ç¿ëµÇ´Â ±âº» ¿ä¼ÒÀÔ´Ï´Ù. ÇÏÁö¸¸ ÀÌ ¸ÅÅ©·Î°¡ Ç×»ó
DECLARE_MODULEÀ̶õ À̸§À¸·Î ³ªÅ¸³ª´Â °ÍÀº ¾Æ´Õ´Ï´Ù. ƯÁ¤ ŸÀÔÀ¸·Î ¸ðµâÀ» ´õ ½±°Ô Á¤ÀÇÇϱâ
À§ÇØ ´Ù¸¥ À̸§À» °®±âµµ ÇÑ´Ù´Â °ÍÀÌÁÒ. ÇÏÁö¸¸ º»ÁúÀûÀ¸·Î °°Àº ÀÏÀ» ¼öÇàÇÕ´Ï´Ù.
DECLARE_MODULEÀº ÀÌ¹Ì ¾ð±ÞÇßµíÀÌ ´ÙÀ½°ú °°Àº ¸ÅÅ©·ÎÀÏ »ÓÀÔ´Ï´Ù.
#define DECLARE_MODULE(name, data, sub, order) \
SYSINIT(name##module, sub, order, module_register_init, &data) \
struct __hack
À̰ÍÀº /usr/include/sys/module.h¿¡ Á¤ÀǵǾî ÀÖ½À´Ï´Ù. ÀÌÁ¦ °¢°¢ÀÇ ¸Å°³ º¯¼öÀÇ Àǹ̸¦ »ìÆì º¾½Ã´Ù.
name : ÀϹÝÀûÀÎ ¸ðµâÀÇ À̸§À¸·Î SYSINIT È£Ãâ¿¡¼ »ç¿ëµË´Ï´Ù.
data : module_data ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅÍ·Î ÀÌ ±¸Á¶Ã¼´Â ´ÙÀ½°ú °°Àº µÎ °¡Áö ÁÖ¿ä ¾ÆÀÌÅÛÀ» Æ÷ÇÔÇϰí
ÀÖ½À´Ï´Ù.
* char* name;
°ø½ÄÀûÀÎ ¸ðµâÀÇ À̸§À¸·Î module ±¸Á¶Ã¼¿¡¼ »ç¿ëµË´Ï´Ù.
* modeventhand_t evhand;
À̰ÍÀÌ ·Îµå Çڵ鷯 ÇÔ¼öÀÇ Æ÷ÀÎÅÍÀÔ´Ï´Ù. µû¶ó¼ ÀÌ Çʵå´Â ÀÛ¼ºÇÏ´Â ¸ðµâÀÇ ·Îµå Çڵ鷯 ÇÔ
¼ö À̸§ÀÌ µÇ°ÚÁÒ.
sub : À̰͵µ SYSINIT ¸ÅÅ©·Î¿¡°Ô ¹Ù·Î Àü´ÞµÇ´Â ¸Å°³ º¯¼öÀε¥, ÀÌ °ªÀº /usr/include/sys/kernel.h¿¡
ÀÖ´Â system_sub_id ³ª¿ ¸®½ºÆ®ÀÇ °ª Áß Çϳª°¡ µË´Ï´Ù. ³ª¿ ¸®½ºÆ®ÀÇ °ªµéÀº ½Ã½ºÅÛ ÃʱâÈ ÀÎÅÍÆä
À̽º(system startup interface)¿¡°Ô ¾Ë·ÁÁø °ªµéÀÔ´Ï´Ù. °¡·É, µð¹ÙÀ̽º·Î »ç¿ëµÇ´Â KLD¸¦ °³¹ßÇÒ ¶§´Â
SI_SUB_DRIVERS ŸÀÔÀÌ ÁöÁ¤µÉ ¼ö ÀÖ½À´Ï´Ù.
order : ÀÌ ¸Å°³ º¯¼ö´Â SYSINITÀÇ È£Ãâ ÈÄ¿¡ »ç¿ëµÇ´Âµ¥, ÀÌ °ªÀº ¼ºê ½Ã½ºÅÛ¿¡¼ÀÇ KLSµéÀÇ ÃʱâÈ
¼ø¼¸¦ ³ªÅ¸³À´Ï´Ù. ÀÌ ÇʵåÀÇ À¯È¿ °ªµéÀº /usr/include/sys/kernel.h¿¡ ÀÖ´Â sysinit_elem_order ³ª¿
¸®½ºÆ®ÀÇ °ªµé Áß ÇϳªÀÔ´Ï´Ù.
±×·¸Áö¸¸ »ó´çÈ÷ À¯¿ëÇÑ µÎ°³ÀÇ ´Ù¸¥ *_MODULE ¸ÅÅ©·Î°¡ Àִµ¥, SYSCALL_MODULE°ú
DEV_MODULEÀÌ ±×°ÍÀÔ´Ï´Ù. ÀÌ ¸ÅÅ©·ÎµéÀº DECLARE_MODULE ¸ÅÅ©·Î¸¦ ·¦ÇÎ(wapping)ÇÑ °ÍÀÌÁÒ.
ÀÌ ¸ÅÅ©·ÎµéÀº 1) ½Ã½ºÅÛ ÄÝÀ̳ª µð¹ÙÀ̽º µå¶óÀ̹ö ¸ðµâÀ» ÀÛ¼ºÇϱ⠽±µµ·Ï ¼³°èµÇ¾úÀ» »Ó ¾Æ´Ï¶ó 2)
¸ðµâ Äڵ带 ´õ Àб⠽¬¿î ¹æ½ÄÀ¸·Î ±â¼úÇÒ ¼ö ÀÖ°Ô ÇØ ÁÝ´Ï´Ù. ¸¸¾à SYSCALL_MODULE ¸ÅÅ©·Î°¡ »ç
¿ëµÈ Äڵ带 Àд´ٸé ÀÌ Äڵ尡 ½Ã½ºÅÛ ÄÝÀ» ÀÛ¼ºÇϱâ À§ÇÑ °ÍÀ̶ó´Â »ç½ÇÀ» ±×¸¸Å ½±°Ô ¾Ë¾Æ Â÷¸±
¼ö ÀÖ°ÚÁÒ.
SYSCALL_MODULE ¸ÅÅ©·Î´Â /usr/include/sys/sysent.h¿¡ Á¤ÀǵǾî ÀÖÀ¸¸ç, ´ÙÀ½°ú °°Àº ¸Å°³ º¯¼ö°¡
ÇÊ¿äÇÕ´Ï´Ù.
name : DECLARE_MODULE¿¡¼ÀÇ name°ú °°Àº Àǹ̷Π»ç¿ëµË´Ï´Ù.
offset : ½Ã½ºÅÛ ÄÝÀÇ ¹øÈ£¸¦ ³Ñ±â´Âµ¥ »ç¿ëµË´Ï´Ù. KLD¸¦ »ç¿ëÇÏ¿© ½Ã½ºÅÛ ÄÝÀ» ÀÛ¼ºÇÑ´Ù¸é º¸Åë ±× ½Ã
½ºÅÛ ÄÝÀº ¿¹¾àµÈ ¹øÈ£°¡ ¾øÀ» °æ¿ì°¡ ¸¹½À´Ï´Ù. ÀÌ·¯ÇÑ °æ¿ì, ÀÌ ¸Å°³ º¯¼ö¿¡ ÀûÇÕÇÑ °ªÀº
NO_SYSCALLÀÔ´Ï´Ù. ÀÌ °ªÀÇ Àǹ̴ ¼ºê ½Ã½ºÅÛ¿¡°Ô ±âÁ¸ ½Ã½ºÅÛ ÄÝÀÌ »ç¿ëÇÏÁö ¾Ê´Â ÀûÀýÇÑ °ªÀ»
ã¾Æ ³Ö¾î ´Þ¶ó´Â ÀǹÌÀÔ´Ï´Ù.
new_sysent : »õ·Î¿î ½Ã½ºÅÛ ÄÝÀ» À§ÇØ Á¤ÀÇµÈ sysent ±¸Á¶Ã¼¸¦ ÀǹÌÇÕ´Ï´Ù.
evh : modeventhand_t ·Îµå Çڵ鷯ÀÇ ÇÔ¼ö Æ÷ÀÎÅÍÀÔ´Ï´Ù.(À§ÀÇ module_data ±¸Á¶Ã¼¿¡¼ÀÇ evhand¿Í
°°½À´Ï´Ù.)
arg : syscall_module_data ±¸Á¶Ã¼¿¡¼ »ç¿ëµÇ´Â °ªÀÔ´Ï´Ù. ÀÌ ¸Å°³ º¯¼ö´Â º¸Åë NULL·Î ¼³Á¤µË´Ï´Ù.
DEV_MODULE ¸ÅÅ©·Î´Â /usr/include/sys/conf.h¿¡ Á¤ÀǵǾî ÀÖÀ¸¸ç, ´ÙÀ½°ú °°Àº ¸Å°³ º¯¼ö°¡ ÇÊ¿äÇÕ
´Ï´Ù.
name : À§ÀÇ µÎ *_MODULE ¸ÅÅ©·Î¿¡¼¿Í °°Àº Àǹ̷Π»ç¿ëµË´Ï´Ù.
evh : modeventhand_t ·Îµå Çڵ鷯ÀÇ ÇÔ¼ö Æ÷ÀÎÅÍÀÔ´Ï´Ù.
arg : module_data ±¸Á¶Ã¼¿¡¼ »ç¿ëµË´Ï´Ù¸é º¸ÅëÀº NULL·Î ¼³Á¤ÇÕ´Ï´Ù.
¿©·¯ºÐÀÇ ¸ðµâÀÌ ¾î¶»°Ô °³¹ßµÇ´À¾ß¿¡ µû¶ó ´Ù¸£°ÚÁö¸¸ Àû¾îµµ ÇϳªÀÇ ·Îµå Çڵ鷯¿Í *_MODULE ¸ÅÅ©
·Î¸¦ °®°Ô µË´Ï´Ù. ÀÌ Æ©Å丮¾ó¿¡¼´Â Çϳª ÀÌ»óÀÇ ·Îµå Çڵ鷯¿Í ¸ÅÅ©·Î°¡ ÇÊ¿äÇÑ »óȲÀº °í·ÁÇÏÁö ¾Ê
½À´Ï´Ù.
´ë½Å ÀÌ·¯ÇÑ »óȲÀ» ¼³¸íÇÑ [ref.2]¸¦ ¿¬°áÇØ ³õ°Ú½À´Ï´Ù. ÂüÁ¶ ¹®¼´Â ¸ðµâ¿¡ ´ëÇÑ º¸´Ù ½Éµµ ±íÀº ³í
ÀǸ¦ Çϰí ÀÖÀ¸¸ç, ´Ù¼öÀÇ ÈǸ¢ÇÑ ¿¹Á¦ Äڵ带 Æ÷ÇÔÇϰí ÀÖÀ¸¹Ç·Î º¸´Ù ¼öÁØ ³ôÀº ¿¹Á¦¸¦ ¿øÇÏ´Â µ¶ÀÚ¿¡
°Ô ÃßõÇÕ´Ï´Ù.
ÀϹÝÀûÀ¸·Î »ç¿ëÇØ¿Â Makefile¿¡´Â ¹Ì¸® Á¤ÀÇµÈ º¯¼öÀÇ ÁýÇÕÀÌ ÀÖ½À´Ï´Ù. ÀÌÁ¦ ÀÌ º¯¼öµéÀ» ¼³Á¤Çϰí
MakefileÀ» È£ÃâÇϱ⸸ ÇÏ¸é ¸ðµç ÀÏÀº ³¡³³´Ï´Ù. ÀÌ·¯ÇÑ °úÁ¤ ¶§¹®¿¡ KLD¸¦ ÄÄÆÄÀÏÇϱâ À§ÇÑ
Makefile ÀÛ¼º ¶§¹®¿¡ °ñ¸Ó¸® ¾ÎÀ» Çʿ䰡 ¾ø½À´Ï´Ù.
".include" ¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Â MakefileÀº /usr/share/mk¿¡ ÀÖ½À´Ï´Ù.
ÇÏÁö¸¸ ¿ì¸®°¡ °ü½ÉÀÖ´Â ".include"´Â [ref.3]¿¡ ÀÖ½À´Ï´Ù. ¿©·¯ºÐ ½º½º·Î MakefileÀ» ÀÛ¼ºÇϱâ Àü¿¡
[ref.3]ÀÇ Makefile »ó´Ü¿¡ ÀÖ´Â ÁÖ¼®À» ÀÐ¾î º¸½Ã±â ¹Ù¶ø´Ï´Ù.
¿©·¯ºÐÀÌ ¼³Á¤ÇØ¾ß ÇÏ´Â ÇÙ½É º¯¼öµéÀº ¸î °³ µÇÁö ¾Ê½À´Ï´Ù.
SRCS : ¼Ò½ºµéÀÇ ¸ñ·Ï
KMOD : ºôµåÇØ¾ß ÇÏ´Â ¸ðµâÀÇ À̸§
ÀÌ ¿Ü¿¡µµ À¯¿ëÇÑ º¯¼öµéÀº ¸¹ÀÌ ÀÖ½À´Ï´Ù. ".include" ¿Í ÇÔ²² MakefileÀ» »ç¿ëÇÏ´Â ¿¹Á¦´Â ´ÙÀ½ ÆäÀÌ
ÁöºÎÅÍ ³ª¿À´Â »À´ë ÄÚµå¿Í ÇÔ²² ¼Ò°³µË´Ï´Ù. ¾Ö½á Áߺ¹ ÅõÀÚÇÒ ÇÊ¿ä´Â ¾ø½À´Ï´Ù. ƯÈ÷ Makefile°ú °°ÀÌ
»ç¼ÒÇÑ °Í¿¡´Â ´õ¿í ±×·¸ÁÒ.
KLD Syscall Implementation Skeleton
ÀÌ Àý¿¡¼´Â µ¿Àû Ä¿³Î ¸µÄ¿ ÀÎÅÍÆäÀ̽º(dynamic kernel linker interface)¸¦ ÀÌ¿ëÇÏ¿© ½Ã½ºÅÛ ÄÝÀ» Ãß
°¡ÇÏ´Â ¾ÆÁÖ ÀϹÝÀûÀÎ ¿¹Á¦°¡ ¼Ò°³µË´Ï´Ù.
¼Ò°³µÉ ÄÚµå´Â ¾çÀÌ ¸¹Áø ¾ÊÁö¸¸ Áß¿äÇÑ Äڵ尡 Æ÷ÇԵǾî ÀÖ½À´Ï´Ù. °Ô´Ù°¡ ÀÌ ÄÚµåµéÀº ½Ã½ºÅÛ ÄÝÀ» Ãß
°¡ÇÏ´Â ¸ðµç ¸ðµâ¿¡ °øÅëÀûÀ¸·Î Æ÷ÇԵ˴ϴÙ. ÄÚµå´Â Å©°Ô ³× °³ÀÇ ÁÖ¿ä ºÎºÐÀ¸·Î ³ª´¯´Ï´Ù. ¹°·Ð ·Îµå
Çڵ鷯¿Í DECALRE_MODULE ¸ÅÅ©·Î´Â Á¦¿ÜÇÏ°í ³ª´« °ÍÀÔ´Ï´Ù.
- syscallname_args ±¸Á¶Ã¼¸¦ Á¤ÀÇÇÕ´Ï´Ù.
- ½Ã½ºÅÛ ÄÝÀÌ µÉ ÇÔ¼ö´Â int ÇüÀ» ¸®ÅÏ °ªÀ¸·Î °®À¸¸ç, Á¤Àû ÇÔ¼ö(static function)À¸·Î ¼±¾ðµÇ¾î¾ß
ÇÕ´Ï´Ù.
- sysent ±¸Á¶Ã¼ÀÇ ¸â¹ö º¯¼öµéÀ» ±¸ÇöÇÏ·Á´Â ½Ã½ºÅÛ ÄÝ¿¡ ¸Â°Ô ¼³Á¤ÇÕ´Ï´Ù.
- offset º¯¼ö¸¦ NO_SYSCALL·Î ¼³Á¤ÇÕ´Ï´Ù.
Ä¿³Î Äڵ忡¼ ¹ß°ßÇÒ ¼ö ÀÖ´Â ¸ðµç ½Ã½ºÅÛ ÄݵéÀÇ ¸Å°³ º¯¼ö ¸ñ·ÏÀº ´ÙÀ½°ú °°½À´Ï´Ù.
-struct proc*
-struct syscallname_args*
»ç¿ëÀÚ ¿µ¿ª¿¡¼ ½Ã½ºÅÛ ÄÝ·Î Àü´ÞµÇ¾î¾ß ÇÏ´Â ¸Å°³ º¯¼öµéÀº syscallname_args ±¸Á¶Ã¼¿¡ Á¤ÀǵǾî ÀÖ
½À´Ï´Ù. ¿ì¸®°¡ proc ±¸Á¶Ã¼¿Í arguments ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ³Ñ±âÁö ¾Ê°íµµ ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÒ
¼ö ÀÖ´Â ÀÌÀ¯´Â ÀÌ ÀÛ¾÷À» libc°¡ ´ë½ÅÇØ Áֱ⠶§¹®ÀÔ´Ï´Ù.
¿ì¸®´Â µ¿ÀûÀ¸·Î ½Ã½ºÅÛ ÄÝÀ» Ãß°¡½ÃŰ´Â °ÍÀ̰í, libc¿¡°Ô ¿ì¸®ÀÇ ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇØ ÁÙ ¼ö ÀÖ´Â ±â´É
À» Ãß°¡ÇÏÁö ¾Ê±â ¶§¹®¿¡ »õ·Î ÀÛ¼ºÇÑ ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÏ·Á¸é syscall(2)À» »ç¿ëÇØ¾ß ÇÕ´Ï´Ù.
ÀÌ·¯ÇÑ ³»¿ëÀº ¿¹Á¦¸¦ ¼Ò°³ÇÏ¸é¼ Á¶±Ý ´õ ¼³¸íÇÏ°Ô µÉ °ÍÀÔ´Ï´Ù.
ÀÌ ¿¹Á¦¿¡¼ ¿ì¸®´Â ´ÙÀ½°ú °°Àº ½Ã½ºÅÛ ÄÝ ¸Å°³ º¯¼ö¸¦ »ç¿ëÇÕ´Ï´Ù.
struct sc_example_args {
char *str;
int val;
};
¸Å°³ º¯¼ö¿¡ ¹®ÀÚ¿ Æ÷ÀÎÅÍ(character string pointer)¿Í Á¤¼ö(integer)¸¦ Æ÷ÇÔ½ÃŲ ÀÌÀ¯´Â ÀÌ µÎ ŸÀÔÀÇ
ÀÚ·áÇüÀ» ½Ã½ºÅÛ ÄÝ·Î ³Ñ±â´Â ¹æ¹ýÀ» º¸¿©ÁÖ±â À§ÇÔÀÔ´Ï´Ù.(»ç¿ëÀÚ ¿µ¿ª¿¡¼ Ä¿³Î ¿µ¿ªÀ¸·Î µ¥ÀÌÅ͸¦ ³Ñ
±â´Â °ÍÀÌ ´ëÇ¥ÀûÀÎ ¿¹°ÚÁÒ.)
´ÙÀ½ÀÌ ¹Ù·Î ¿¹Á¦ ½Ã½ºÅÛ ÄÝÀÇ ÄÚµåÀÔ´Ï´Ù.
static int
sc_example(struct proc *p, struct sc_example_args *uap)
{
char kstr[1024+1]; /* Holds kernel land copy of uap->str */
int err = 0; /* Generic return(err) */
int size = 0;
/*
* _IMPORTANT_:
*
* When one has a contiguous set of data and wish to copy this from
* userland to kernel land (or vice versa) the copy(9) functions
* are recommended for doing this.
*/
/*
* Copy the string located at the user land address uap->str to
* the kernel land address of &kstr.
*/
err = copyinstr(uap->str, &kstr, 1024, &size);
if (err == EFAULT)
return(err);
/*
* Print out the values we have gathered.
*
* uprintf() is a kernel land function that acts like printf().
* When using the printf() in kernel land, it uses the dmesg
* facility.. uprintf() on the other hand will output directly to
* the currently used tty.
*/
uprintf("The string passed was: %s\n", kstr);
uprintf("The value passed was: %d\n", uap->val);
return(0);
}
ÀÌ ÇÔ¼ö´Â Àü´ÞµÇ´Â ¸Å°³ º¯¼ö(ÇϳªÀÇ ¹®ÀÚ¿°ú Á¤¼ö)¸¸À» ³Ñ°Ü ¹ÞÀº ÈÄ, ±× °ªÀ» ÇöÀç ÀÛ¾÷Çϰí ÀÖ´Â
tty(½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÑ ÇÁ·Î±×·¥ÀÌ ¼öÇàµÇ°í ÀÖ´Â Å͹̳Î)¿¡ Ãâ·ÂÇÕ´Ï´Ù.
´ÙÀ½¿¡ ÇØ¾ß ÇÒ ÀÏÀº ½Ã½ºÅÛ ÄÝÀ» À§ÇØ sysent ±¸Á¶Ã¼ÀÇ ³»¿ëÀ» ä¿ö³Ö´Â ÀÏÀÔ´Ï´Ù. Sysent ±¸ÃÊÁ¦´Â
/usr/include/sys/sysent.h¿¡ Á¤ÀǵǾî ÀÖÀ¸¸ç, ´ÙÀ½°ú °°½À´Ï´Ù.
struct sysent {
int sy_narg;
sy_call_t *sy_call;
};
°¢ ½Ã½ºÅÛ Äݸ¶´Ù Á¤ÀÇµÈ sysent ±¸Á¶Ã¼¸¦ °®°í ÀÖ½À´Ï´Ù. 'int sy_narg'´Â Á¤ÀÇµÉ ½Ã½ºÅÛ ÄÝ¿¡°Ô ¾ó¸¶³ª
¸¹Àº ¸Å°³ º¯¼ö°¡ ³Ñ¾î¿Ã °ÍÀÎÁö¸¦ °áÁ¤ÇÏ´Â º¯¼öÀÔ´Ï´Ù. ¿ì¸®ÀÇ »À´ë Äڵ忡¼´Â 2°³ÀÇ ¸Å°³ º¯¼ö¸¸ÀÌ
³Ñ¾î¿É´Ï´Ù.(char* str°ú int val) µû¶ó¼ sy_narg´Â 2·Î ¼³Á¤ÇÕ´Ï´Ù. 'sy_call_t* sy_call'Àº static int
syscall¿¡ ´ëÇÑ ÇÔ¼ö Æ÷ÀÎÅÍÀÔ´Ï´Ù. Sy_call_t´Â /usr/include/sys/sysent.h¿¡ Á¤ÀǵǾî ÀÖÀ¸¸ç ´ÙÀ½°ú °°
½À´Ï´Ù.
typedef int sy_call_t __P((struct proc *, void *));
µû¶ó¼ ¿ì¸® Äڵ忡¼´Â ´ÙÀ½°ú °°ÀÌ ¼³Á¤µÉ °ÍÀÔ´Ï´Ù.
static struct sysent sc_example_sysent = { 2, /* Number of parameters for our system call. */
sc_example /* A function pointer to our new system call. */ };
ÀÌÀüÀÇ ¼³¸íÀ» ±â¾ïÇÑ´Ù¸é SYSCALL_MODULE ¸ÅÅ©·Î¿¡°Ô ³Ñ¾î¿Â offsetÀ̶ó´Â ¸Å°³ º¯¼ö°¡ ÀÖ¾ú´Ù´Â
»ç½ÇÀ» ¾Ë°í ÀÖÀ» °ÍÀÔ´Ï´Ù. ÀÌ ¸Å°³ º¯¼ö´Â ¼±¾ðÇϰí ÀÖ´Â ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇϴµ¥ »ç¿ëµÉ °ªÀ» ´ã°í
ÀÖ½À´Ï´Ù. ÇÏÁö¸¸ º¸Åë KLD °°Àº °ÍÀ» ÀÌ¿ëÇÏ¿© µ¿ÀûÀ¸·Î ½Ã½ºÅÛ ÄÝÀ» »ý¼ºÇÒ ¶§¿¡´Â ƯÁ¤ÇÑ °ªÀ» Á¤ÇÏ
¿© ³Ñ±âÁö ¾Ê´Â °ÍÀÌ ÁÁ½À´Ï´Ù. º¸Åë ÀÌ °ªÀ» NO_SYSCALL·Î ¼³Á¤ÇÏ´Â °ÍÀÌ ÁÁÀºµ¥, ÀÌ °ªÀÇ Àǹ̴Â
"ÇÒ´ç °¡´ÉÇÑ ´ÙÀ½ ½Ã½ºÅÛ ÄÝ °ªÀ» ã¾Æ´Þ¶ó"´Â °ÍÀÔ´Ï´Ù.(ÀÌ ³»¿ëµµ ÀÌ¹Ì ¼³¸íÇß¾ú½À´Ï´Ù.) µû¶ó¼ ¸ÅÅ©
·Î¿¡°Ô offset °ªÀ¸·Î NO_SYSCALL¸¸À» ³Ñ±â¸é ½Ã½ºÅÛ ÄÝ ¹øÈ£ÀÇ ¹®Á¦´Â ÇØ°áµÉ °ÍÀÔ´Ï´Ù. ÇÏÁö¸¸ ¾î
¶² Á¤Àû º¯¼ö °ªÀ» NO_SYSCALL·Î ¼³Á¤ÇÑ ÈÄ ±× º¯¼ö¸¦ ³Ñ±â´Â ¹æ½ÄÀÌ ´õ ÃßõµÇ´Âµ¥, ÀÌ·¸°Ô Çϸé
¸ðµâÀ» ·ÎµåÇÒ ¶§ ÀÌ º¯¼öÀÇ °ªÀÌ ¹«¾ùÀ¸·Î ¼³Á¤µÇ¾î ÀÖ´ÂÁö¸¦ ¾Ë ¼ö Àֱ⠶§¹®ÀÔ´Ï´Ù. ÀÌ ¸ÅÅ©·Î´Â
NO_SYSCALLÀ» ´ã°í ÀÖ´ø º¯¼ö¸¦ ½Ã½ºÅÛÀÌ ÇÒ´çÇØ ÁØ ¹øÈ£·Î º¯°æ½Ãŵ´Ï´Ù. ½Ã½ºÅÛ¿¡ ÀÌ¹Ì Á¤ÀǵǾî
ÀÖ´Â ½Ã½ºÅÛ Äݰú ±× È£Ãâ ¹øÈ£´Â /usr/include/sys/syscall.h¿¡ Á¤ÀǵǾî ÀÖ½À´Ï´Ù.
ÀÌ·± ÀÌÀ¯·Î ¿ì¸®´Â ÄÚµåÀÇ ´ÙÀ½ ¶óÀÎÀ» ´ÙÀ½°ú °°ÀÌ ÀÛ¼ºÇÒ °ÍÀÔ´Ï´Ù.
static int syscall_num = NO_SYSCALL;
NO_SYSCALLÀº /usr/include/sys/sysent.h¿¡ Á¤ÀǵǾî Àִµ¥, (-1)·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.
¿ì¸®´Â ÀÌ¹Ì ÇϳªÀÇ ½Ã½ºÅÛ ÄÝÀ» ±¸ÇöÇϴµ¥ ÇÊ¿äÇÑ ¸ðµç ºÎºÐÀ» ¿Ï¼ºÇß½À´Ï´Ù. µû¶ó¼ ³²Àº ºÎºÐÀº ·Î
µå Çڵ鷯¸¦ ÀÛ¼ºÇϰí SYSCALL_MODULE ¸ÅÅ©·Î È£ÃâÇÏ´Â °Í »ÓÀÔ´Ï´Ù.
static int
load_handler(struct module *m, int what, void *arg)
{
int err = 0;
switch (what) {
case MOD_LOAD:
/* Print out syscall_num so we know the value to call */
printf("System call loaded at slot: %d\n", syscall_num);
break;
case MOD_UNLOAD:
printf("System call unloaded from slot: %d\n", syscall_num);
break;
default:
err = EINVAL;
break;
}
return(err);
}
SYSCALL_MODULE(sc_example,
&syscall_num,
&sc_example_sysent,
load_handler,
NULL);
ÀÌÁ¦ ¿ì¸®ÀÇ »À´ë Äڵ尡 ¿Ï¼ºµÇ¾ú½À´Ï´Ù. (ÁÖ¼®¾ø´Â ÄÚµå´Â [ref. 4]¿¡¼ ¾òÀ» ¼ö ÀÖ½À´Ï´Ù.) ÀÌÁ¦ ÄÄÆÄ
ÀÏÇÒ Áغñ°¡ ´Ù µÇ¾ú±º¿ä. ±×·¸´Ù¸é ´ÙÀ½°ú °°ÀÌ °£´ÜÇÑ MakefileÀ» ÀÛ¼ºÇսôÙ.
SRCS=sc_example.c
KMOD=sc_example
.include <bsd.kmod.mk>
±×¸®°í make¶ó°í ŸÀÌÇÎÇϽʽÿÀ. ÀÌÁ¦ ÄÄÆÄÀÏÀÌ ³¡³µ´Ù¸é ·çÆ® ±ÇÇÑÀ¸·Î ´ÙÀ½°ú °°ÀÌ ÀÔ·ÂÇϼ¼¿ä.
'kldload ./sc_example.ko'
Áö±Ý±îÁöÀÇ °úÁ¤¿¡ ¾î¶² ¿¡·¯°¡ ¾ø¾ú´Ù¸é ´ÙÀ½°ú °°Àº Ãâ·Â¹°À» º¼ ¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù.
System call loaded at slot: 210
¿©±â¿¡¼ ³íÀǵÇÁö ¾ÊÀº Á¡Àº ½Ã½ºÅÛ ÄÝÀÌ ·ÎµåµÈ ÈÄ, ¾î¶»°Ô ÀÌ ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇϴ°¡ ÇÏ´Â °ÍÀÔ´Ï´Ù.
ÇÏÁö¸¸ [ref.4]¿¡¼ Á¦°øµÇ´Â Äڵ带 ÂüÁ¶Çϸé ÀÌ ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÏ´Â ¸î °¡Áö ´Ù¸¥ ¹æ¹ýÀÇ ¿¹¸¦ º¼
¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù. ¶ÇÇÑ syscall(2)ÀÇ man pageµµ ÀÐ¾î º¸½Ã±â ¹Ù¶ø´Ï´Ù.
Character Device KLD Implementation Skeleton
´ëºÎºÐÀÇ À¯´Ð½º ½Ã½ºÅÛ¿¡¼ °¡Àå À¯¿ëÇÏ°Ô »ç¿ëµÇ´Â µð¹ÙÀ̽ºÀÇ ÇüÅ´ ij¸¯ÅÍ(character) µð¹ÙÀ̽ºÀÔ
´Ï´Ù. ÀÌ·¯ÇÑ ÇüÅÂÀÇ µð¹ÙÀ̽º´Â ¹°¸® µð¹ÙÀ̽º(physical device)¸¦ ³ªÅ¸³»´Âµ¥ »ç¿ëµÇ´Â °Í »Ó ¾Æ´Ï¶ó
Ä¿³ÎÀÇ Æ¯Á¤ ºÎºÐÀ» Àаí, ¾²°í, Ç÷¡±×¸¦ ¼³Á¤Çϱâ À§ÇÑ ÀÎÅÍÆäÀ̽º·Î »ç¿ëµÇ±âµµ ÇÕ´Ï´Ù. °¡·É, ij¸¯ÅÍ
µð¹ÙÀ̽º¸¦ ¼³Á¤ÇÏ¿© ³×Æ®¿öÅ© Æ®·¡ÇÈ(network traffic)°ú °ü·ÃµÈ µð¹ÙÀ̽º·ÎºÎÅÍ µ¥ÀÌÅ͸¦ ÀÐ¾î ¿À´Â °Í
µµ °¡´ÉÇÕ´Ï´Ù.
½Ã½ºÅÛ ÄÝ ±¸Çö°ú °°ÀÌ Ä³¸¯ÅÍ µð¹ÙÀ̽ºÀÇ Á¦ÀÛµµ ¿¹Á¦ Áß½ÉÀ¸·Î ÁøÇàµÉ °ÍÀÔ´Ï´Ù. ÀÌ µð¹ÙÀ̽º°¡ °¡Áø
±â´ÉÀº ½Ç·Î ¹Ì¾àÇÏÁö¸¸ ¸ðµç ij¸¯ÅÍ µð¹ÙÀ̽ºÀÇ ÀϹÝÀûÀΠƯ¼ºÀ» ÆÄ¾ÇÇÏ´Â µ¥´Â ¹«¸®°¡ ¾ø´Â ¿¹ÀÏ °Í
ÀÔ´Ï´Ù. ¾ÕÀ¸·Î ÁøÇàµÉ ¼³¸íÀ» ÅëÇØ ¿©·¯ºÐÀÌ Ä³¸¯ÅÍ µð¹ÙÀ̽ºÀÇ Á¦ÀÛÀÌ ±×·¸°Ô ¾î·Á¿î °ÍÀº ¾Æ´Ï¸ç, ÀÌ
µð¹ÙÀ̽º¸¦ Á¦ÀÛÇÏ¿© »ç¿ëÇÏ´Â °ÍÀÌ »ó´çÈ÷ À¯¿ëÇÏ´Ù´Â »ç½ÇÀ» ±ú´ÞÀ» ¼ö ÀÖÀ¸¸é ÇÕ´Ï´Ù.
´ÙÀ½°ú °°Àº Á¡µéÀº ¸ðµç ij¸¯ÅÍ µð¹ÙÀ̽ºÀÇ ±¸Çö¿¡ °øÅëÀûÀÎ ºÎºÐÀÔ´Ï´Ù.
- ¿øÇü µð¹ÙÀ̽º ÇÔ¼öµé(prototype device functions)
- cdevsw ±¸Á¶Ã¼ ¼±¾ð
- ¼±¾ðµÈ cdevsw ±¸Á¶¿¡ µû¸¥ ÇÔ¼öµé
- ·Îµå Çڵ鷯¿Í DEV_MODULE ¸ÅÅ©·Î
À§¿Í °°Àº °ÍµéÀÌ ¾ÕÀ¸·Î ¸¸µé¾î ³ª°¥ »À´ë Äڵ忡 Æ÷Ç﵃ ³»¿ëµéÀÔ´Ï´Ù. ½Ã½ºÅÛ ÄÝ ¿¹Á¦ ÄÚµå¿Í ¸¶Âù°¡
Áö·Î ÁÖ¼® ¾ø´Â Äڵ带 ¿øÇÑ´Ù¸é [ref.4]¸¦ ÂüÁ¶ÇϽñ⠹ٶø´Ï´Ù. ÄÄÆÄÀÏÇÏ°í ½ÇÇà½ÃÄÑ º¸´Â °ÍÀÌ ÄÚµå
¸¦ ºÐ¼®Çϴµ¥ »ó´çÈ÷ Å« µµ¿òÀÌ µÈ´Ù´Â »ç½ÇÀ» ±â¾ïÇϽʽÿÀ.
¿©±â¿¡¼ ÇÁ·ÎÅäŸÀÔ(prototype)À» ¸¸µé ÇÔ¼ö´Â ´ÜÁö »õ·Î¿î µð¹ÙÀ̽º¿¡ ¹Ù·Î Á¢±ÙÇϱâ À§ÇØ È£ÃâµÇ´Â
ÇÔ¼öµéÀ̸ç, cdevsw ±¸Á¶Ã¼¿¡ Æ÷ÇԵ˴ϴÙ. ÀÌ·¯ÇÑ ÇÔ¼ö·Î´Â µð¹ÙÀ̽º¸¦ ¿°í, ´Ý°í, ¾²°í, Àд ÇÔ¼ö¸¦
µé ¼ö ÀÖ½À´Ï´Ù.
d_open_t example_open;
d_close_t example_close;
d_read_t example_read;
d_write_t example_write;
cdevsw ±¸Á¶Ã¼¿¡´Â ¿ì¸®°¡ ±¸ÇöÇϰí Àִ ij¸¯ÅÍ µð¹ÙÀ̽º¿Í °ü·Ã ÀÖ´Â ¸¹Àº °ÍµéÀÌ Á¤Àǵ˴ϴÙ. ÀÌ ±¸
Á¶Ã¼´Â /usr/include/sys/conf.h¿¡ Á¤ÀǵǾî ÀÖÀ¸¸ç, ´ÙÀ½°ú °°½À´Ï´Ù.
struct cdevsw {
d_open_t *d_open; /* Func. pointer to dev open function */
d_close_t *d_close; /* Func. pointer to dev close function */
d_read_t *d_read; /* Func. pointer to dev read function */
d_write_t *d_write; /* Func. pointer to dev write function */
d_ioctl_t *d_ioctl; /* Func. pointer to dev ioctl function */
d_poll_t *d_poll; /* Func. pointer to dev poll function */
d_mmap_t *d_mmap; /* Func. pointer to dev mmap function
*/
d_strategy_t *d_strategy; /* Func. pointer to dev strategy func. */
const char *d_name; /* Device name in /dev */
int d_maj; /* Device major value */
d_dump_t *d_dump; /* Func. pointer to dev dump function */
d_psize_t *d_psize; /* Func. pointer to dev psize function */
u_int d_flags; /* D_TAPE, D_DISK, D_TTY, D_MEM */
int d_bmaj; /* Block Device major value (used by D_DISK) */
};
±¸Á¶Ã¼ ³»ÀÇ ¸ðµç ÇÔ¼ö Æ÷ÀÎÅͰ¡ Á¤ÀǵǾî¾ß ÇÏ´Â °ÍÀº ¾Æ´Õ´Ï´Ù. ÀÌÀ¯°¡ ¹»±î¿ä? ¿©·¯ºÐÀÌ ¾²±â¸¸ °¡
´ÉÇÑ µð¹ÙÀ̽º¸¦ ¿øÇÑ´Ù°í °¡Á¤ÇØ º¾½Ã´Ù. ÀÌ °æ¿ì, ´ÜÁö ÆÄÀÏ Çã°¡±Ç(permission)À» ¼³Á¤ÇÏ´Â °Í ¿Ü¿¡
cdevsw ±¸Á¶Ã¼¸¦ ¼±¾ðÇÒ ¶§ d_read Æ÷ÀÎÅ͸¦ noread·Î ¼³Á¤ÇÒ ¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù.(½ÇÁ¦·Ð ºñ¿ö³õ´Â °Í
ÀÌÁÒ.) ¿ì¸®ÀÇ ¿¹Á¦ Äڵ忡¼´Â ´ÜÁö d_open, d_close, d_write ÇÔ¼ö¸¸À» ¼³Á¤ÇÏ¿© ÃßÈÄÀÇ ³íÀǸ¦ ´Ü¼øÈ
ÇϰڽÀ´Ï´Ù. ±×·¸´Ù¸é ¿ì¸®ÀÇ cdevsw ±¸Á¶Ã¼´Â ´ÙÀ½°ú °°Àº ¸ð½ÀÀ» ÇÏ°Ô µÇ°ÚÁÒ.
static struct cdevsw example_cdevsw = {
example_open,
example_close,
example_read,
example_write,
noioctl,
nopoll,
nommap,
nostrategy,
"example",
33, /* /usr/src/sys/conf/majors */
nodump,
nopsize,
D_TTY,
-1
};
°á±¹ "no*"·Î ½ÃÀ۵Ǵ ¼±¾ðÀ» Á¦¿ÜÇÑ´Ù¸é d_open_t, d_close_t, d_read_t, d_write_t¸¦ À§ÇÑ ÇÔ¼ö¸¸ÀÌ
¼±¾ðµÇ¾î ÀÖ´Â ¼ÀÀÔ´Ï´Ù. ´Ù¸¥ ij¸¯ÅÍ µð¹ÙÀ̽ºÀÇ Äڵ带 ¿øÇÑ´Ù¸é [ref. 5]¸¦ ÂüÁ¶ÇϽʽÿÀ. ÀÌ ¿¹Á¦¿¡
¼´Â d_open_t, d_close_t, d_read_t, d_write_t¸¦ À§ÇÑ °£´ÜÇÑ ¿¹Á¦ ÇÔ¼ö¸¸ÀÌ Á¤Àǵ˴ϴÙ. ¶Ç Çϳª, ÁÖ
¹øÈ£(major value)°¡ 33ÀÎÁö È®ÀÎÇØ º¸½Ã±â ¹Ù¶ø´Ï´Ù. 33Àº ¿¹Á¦ ¸ñÀûÀ¸·Î ¿¹¾àµÈ ÁÖ ¹øÈ£ Áß ÇϳªÀÔ´Ï
´Ù. ÀÌ ¿Ü¿¡ ´Ù¸¥ ¿¹Á¦ ¹øÈ£¸¦ È®ÀÎÇÏ°í ½Í°Å³ª ½ÇÁ¦ »ç¿ëµÉ µð¹ÙÀ̽º¸¦ À§ÇØ ÇÒ´çµÈ ÁÖ ¹øÈ£ °ªÀ» È®ÀÎ
ÇÏ°í ½Í´Ù¸é /usr/src/sys/conf/majors ÆÄÀÏÀ» »ìÆì º¸½Ã±â ¹Ù¶ø´Ï´Ù.
ÀÌ ¿¹Á¦ÀÇ ±âº» Àǵµ´Â µð¹ÙÀ̽º µå¶óÀ̹ö¿ÍÀÇ »óÈ£ ÀÛ¿ëÀÌ ¾î¶»°Ô ÀÌ·ç¾î Áö´Â°¡¸¦ º¸¿© ÁÖ´Â °ÍÀÔ´Ï
´Ù. ÀÌ·¯ÇÑ ÀÌÀ¯·Î ÀÌ µå¶óÀ̹ö¿¡¼ÀÇ ÄÚµå È帧Àº ´ÙÀ½°ú °°Àº ¼ø¼·Î ¼³Á¤Çß½À´Ï´Ù.
open(2) -> write(2) -> read(2) -> close(2).
¿ì¸®´Â ¸ÕÀú /dev/ µð·ºÅ丮¿¡ ÀÖ´Â µð¹ÙÀ̽º¸¦ ¿ °ÍÀÔ´Ï´Ù. ±× ÈÄ, write(2) ½Ã½ºÅÛ ÄÝÀ» »ç¿ëÇÏ¿© ª
Àº ¹®ÀÚ¿À» ¾¹´Ï´Ù. ¿ì¸®°¡ µð¹ÙÀ̽º¿¡ ¾´ ¹®ÀÚ¿Àº ¾î¶² Á¤Àû ¹öÆÛ(static buffer)¿¡ ÀúÀåµÉ °ÍÀ̰í, ÀÌ
°ªÀº read(2) ½Ã½ºÅÛ ÄÝÀ» °ÅÃÄ Á¢±ÙµÉ °ÍÀÔ´Ï´Ù. ÀÌÁ¦ ÀÌ µð¹ÙÀ̽º¸¦ ´Ý¾Æ ´õ ÀÌ»ó Àаųª ¾µ ¼ö ¾øµµ
·Ï ¸¸µì´Ï´Ù.
/* Stores string recv'd by _write() */
static char buf[512+1];
static int len;
/*
* Used as the variable that is the reference to our device
* in devfs... we must keep this variable sane until we
* call kldunload.
*/
static dev_t sdev;
/*
* This open function solely checks for open(2) flags. We are only
* allowing for the flags to be O_RDWR for the purpose of showing
* how one could only allow a read-only device, for example.
*/
int
example_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
int err = 0;
memset(&buf, '\0', 513);
len = 0;
uprintf("Opened device \"example\" successfully.\n");
return(err);
}
/*
* Simply "closes" our device that was opened with example_open.
*/
int
example_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
memset(&buf, '\0', 513);
len = 0;
uprintf("Closing device \"example.\"\n");
return(0);
}
/*
* The read function just takes the buf that was saved
* via example_write() and returns it to userland for
* accessing.
*/
int
example_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
if (len <= 0) {
err = -1;
} else { /* copy buf to userland */
err = copystr(&buf, uio->uio_iov->iov_base, 513, &len);
}
return(err);
}
/*
* example_write takes in a character string and saves it
* to buf for later accessing.
*/
int
example_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
err = copyinstr(uio->uio_iov->iov_base, &buf, 512, &len);
if (err != 0) {
uprintf("Write to \"example\" failed.\n");
}
return(err);
}
Áö±Ý±îÁö »ìÆì º» ¹Ù¿Í °°ÀÌ °£´ÜÇÑ Ä³¸¯ÅÍ µð¹ÙÀ̽º µå¶óÀ̹ö¸¦ ÀÛ¼ºÇÏ´Â °ÍÀº ¸Å¿ì ½¬¿î ÀÏÀÌ´Ù. ƯÈ÷,
sysctl·Î °¡´ÉÇÑ ¾ç ÀÌ»óÀ¸·Î ¸¹Àº µ¥ÀÌÅ͸¦ Ä¿³Î°ú ±³È¯ÇÏ°í ½Í´Ù¸é ÀÌ ¹æ¹ýÀº ¸ÚÁø ÇØ°áÃ¥ÀÌ µÉ °ÍÀÔ
´Ï´Ù.
´ÙÀ½¿¡ ³ª¿Ã ÄÚµå´Â ½ÇÁ¦ KLD¸¦ ·ÎµåÇÏ°í ¾ð·ÎµåÇÒ ¶§ »ç¿ëµÇ´Â ÇÔ¼öÀÔ´Ï´Ù. µð¹ÙÀ̽º µå¶óÀ̹öÀÇ °æ¿ì,
·ÎµåÇÏ°í ¾ð·ÎµåÇÒ ¶§ ½Ã½ºÅÛ ÄÝ¿¡¼´Â ÇÏÁö ¾Ê¾Ò´ø Ưº°ÇÑ ÀÛ¾÷À» ¼öÇàÇØ¾ß ÇÕ´Ï´Ù. Áï, MOD_LOAD
½Ã make_dev¸¦ »ç¿ëÇÏ¿© devfs¿¡ ¿ì¸®ÀÇ µð¹ÙÀ̽º¸¦ µî·ÏÇØ¾ß ÇÕ´Ï´Ù. devfs´Â Device File SystemÀÇ
¾à¾î·Î¼ FreeBSD Ä¿³Î ³»ºÎ¿¡ ÀÖ´Â µð¹ÙÀ̽º °ø°£¿¡ Á¢±ÙÇÒ ¼ö ÀÖµµ·Ï ÇØ ÁÝ´Ï´Ù. ¶ÇÇÑ
MOD_UNLOAD ½Ã¿¡´Â destroy_dev¸¦ È£ÃâÇØ¾ß Çϴµ¥, ¸Å°³ º¯¼ö·Î´Â make_dev°¡ ¸®ÅÏÇØ ÁØ dev_t
º¯¼ö°¡ »ç¿ëµÇ¾î¾ß ÇÕ´Ï´Ù.
/*
* chardev_example_load()
*
* This is used as the function that handles what is to occur
* when the KLD binary is loaded and unloaded via the kldload
* and kldunload programs.
*/
static int
chardev_example_load(struct module *m, int what, void *arg)
{
int err = 0;
switch (what) {
case MOD_LOAD: /* kldload */
sdev = make_dev(&example_cdevsw, /* explained below */
0,
UID_ROOT,
GID_WHEEL,
0600,
"example");
printf("Example device loaded.\n");
break;
case MOD_UNLOAD:
destroy_dev(sdev); /* explained below */
printf("Example device unloaded.\n");
break;
default:
err = EINVAL;
break;
}
return(err);
}
´Ù¸¥ Á¾·ùÀÇ KLD¸¦ ¸¸µé ¶§Ã³·³ ±âº»ÀûÀ¸·Î *_MODULE ¸ÅÅ©·Î¸¦ »ç¿ëÇÏ¿© ¾î´À ÇÔ¼ö°¡ ·Îµå Çڵ鷯
ÀÎÁö¿Í ÀÌ ¸ðµâ¿¡ Á¢±ÙÇÒ ¶§ »ç¿ëÇÒ À̸§À» ¾Ë·Á ÁÖ¾î¾ß ÇÕ´Ï´Ù.
DEV_MODULE(chardev_example, chardev_example_load, NULL);
ÀÌÁ¦ ¸Å¿ì °£´ÜÇÑ Ä³¸¯ÅÍ µð¹ÙÀ̽ºÀÇ »À´ë Äڵ尡 ¿Ï¼ºµÇ¾ú½À´Ï´Ù. ÀÌÁ¦ ³²Àº ÀÏÀº MakefileÀ» ¸¸µé°í
/dev µð·ºÅ丮¿¡ µð¹ÙÀ̽º¸¦ ½ÇÁ¦·Î »ý¼ºÇÏ´Â ÀÏ »ÓÀÔ´Ï´Ù. ÀÌ ÀÛ¾÷ ¿ª½Ã °áÄÚ ¾î·Á¿î ÀÛ¾÷ÀÌ ¾Æ´Õ´Ï´Ù.
# cd /dev
# mknod example c 33 0
# ls -al | grep example
crw-r--r-- 1 root wheel 33, 0 Aug 14 04:40 example
#
À§ÀÇ °úÁ¤ÀÌ ³¡³ª¸é kldload¸¦ ¼öÇàÇÑ ÈÄ /dev/example¿¡ open(), close(), read(), write() È£ÃâÀ» ¼öÇà
ÇØ º¸½Ê½Ã¿À. Å×½ºÆ®°¡ ³¡³ ÈÄ kldunload¸¦ ¼öÇàÇÒ ÅÙµ¥, ÀÌ Àü¿¡ ¹Ýµå½Ã close()¸¦ È£ÃâÇÏ¿© µð¹ÙÀ̽º
¸¦ ´Ý¾Æ ÁÖ¾î¾ß ÇÑ´Ù´Â »ç½ÇÀ» ±â¾ïÇϽñ⠹ٶø´Ï´Ù.
¿¹Á¦ÀÇ ÄÄÆÄÀÏ °¡´ÉÇÑ ÄÚµå´Â [ref. 4]¸¦ º¸½Ã±â ¹Ù¶ø´Ï´Ù.
Conclusion À̰ÍÀ¸·Î FreeBSD KLD ÄÚµù ½Ã½ºÅÛ¿¡ ´ëÇÑ ¼Ò°³¸¦ ¸¶¹«¸® ÇØ¾ß ÇÒ °Í °°½À´Ï´Ù. ±ÛÀÇ Ãʹݺο¡ ¸»Çß µíÀÌ ²Ï ªÀº ¼Ò°³¿´Áö¸¸ ´çÀå KLD ÇÁ·Î±×·¥À» ÀÛ¼ºÇϰíÀÚ ÇÏ´Â »ç¶÷¿¡°Ô´Â ²Ï À¯¿ëÇÑ Á¤º¸¿´À¸¸®¶ó »ý°¢ÇÕ´Ï´Ù. ÀÌ ±ÛÀº THC [ref. 2]¸¦ ÂüÁ¶·Î ÇÏ¿© ÀÛ¼ºµÇ¾ú´Âµ¥, THC´Â KLD¸¦ Á» ´õ ÀÚ¼¼È÷ ¹è¿ï ¼ö ÀÖ´Â ÈǸ¢ÇÑ ±â»çÀÔ´Ï´Ù. À̿ܿ¡ ´õ ¸¹Àº ¿¹Á¦ Äڵ带 ¿øÇÏ´Â µ¶ÀÚµéÀº [ref. 4]¸¦ ÂüÁ¶ÇϽñ⠹ٶø´Ï´Ù. [ref. 4]¿¡´Â ÀÌ Æ©Å丮¾ó¿¡¼ ¼³¸íÇÑ °Í ÀÌ»óÀÇ ´Ù¾çÇÑ ¿¹Á¦ Äڵ尡 ¼Ò°³µË´Ï´Ù. Contact ÀÌ Æ©Å丮¾óÀÇ ¾î´À ºÎºÐÀÌ¶óµµ ÀúÀÚ¿¡°Ô ±Ã±ÝÇÑ Á¡ÀÌ ÀÖ´Ù¸é ¹®ÀÇÇØ Áֽñ⠹ٶø´Ï´Ù. E-Mail : awr@blackops.org References 1. kld(4) man page. [Much help] 2. THC's FreeBSD Kernel Attack paper. [Good place for taking your white hat and turning it black] 3. /usr/share/mk/* [Key for any Makefile creation under FreeBSD] 4. Example code from tutorial [Location of the examples plus more code.] 5. /usr/share/example/kld/cdev/ [Old example in FreeBSD tree] Recognition Peter Wemm - Discussion regarding LKM->KLD changes + long quote [intro] Eivind Eklund - style(9) harassment. Daniel O'Connor - Random comments.