\documentclass[letterpaper]{article}
\nonstopmode
\akai
\usepackage{linuxdoc-sgml}
\usepackage{qwertz}
\usepackage{url}
\usepackage[latin1]{inputenc}
\usepackage{t1enc}
\usepackage[english]{babel}
\usepackage{epsfig}
\usepackage{null}
\def\addbibtoc{
\addcontentsline{toc}{section}{\numberline{\mbox{}}\relax\bibname}
}%end-preamble
\setcounter{page}{1}
\title{¦p¦ó¦b Linux ¤U¼¶¼gµ{¦¡¨Ó¨Ï¥Î I/O °ð}
\author{§@ªÌ: Riku Saikkonen {\ttfamily $<$Riku.Saikkonen@hut.fi$>$}\\ 
Ä¶ªÌ: Da-Wei Chiang {\ttfamily $<$dawei@sinica.edu.tw$>$}}
\date{v, 28 December 1997
Â½Ä¶¤é´Á: 22 Jul. - 1 Aug. 1998}
\abstract{¥»¤åªº¤º®e»¡©ú¤F Intel x86 ¬[ºc¤U¦p¦ó¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤¤¼¶¼gµ{¦¡¨Ó¨Ï¥ÎµwÅéI/O °ð¥H¤Îµ¥«Ý¤@¤p¬qªº®É¶¡©P´Á.}


\begin{document}
\maketitle
\tableofcontents

\section{¤¶²Ð}

¥»¤åªº¤º®e»¡©ú¤F Intel x86 ¬[ºc¤U¦p¦ó¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤¤¼¶¼gµ{¦¡¨Ó¨Ï¥ÎµwÅé
I/O °ð¥H¤Îµ¥«Ý¤@¤p¬qªº®É¶¡©P´Á. ¤º®e·½¦Û©ó¤@½g«D±`µuªº¤å³¹
IO-Port mini-HOWTO ¨ä§@ªÌ»P¥»¤å¦P.

¥»¤å 1995-1997 ªºª©ÅvÄÝ©ó Riku Saikkonen ©Ò¦³. ª©ÅvÁn©ú¸Ô¨£ºô­¶
\nameurl{http://sunsite.unc.edu/pub/Linux/docs/HOWTO/COPYRIGHT}{Linux HOWTO copyright}.

¦pªG±z¹ï¥»¤å¦³¥ô¦ó«ü±Ð¤£½×¬O¿ù»~­×¥¿©Î¬O¤º®e¸É­z, ³£Åwªï±H«Hµ¹§Ú
({\ttfamily Riku.Saikkonen@hut.fi})...

¥»¤å¹ï«e¤@¦¸µo¦æªºª©¥» (Mar 30 1997) §@¤F¦p¤Uªº­×¥¿:

\begin{itemize}
\item ¹ï©ó {\ttfamily inb\_p}/{\ttfamily outb\_p} ©M°ð¦ì§} 0x80 ¤§¶¡ªºÃö«Y°µ¥X¤F¼á²M.
\item §R°£¤FÃö©ó {\ttfamily udelay()} ¨ç¦¡ªº¸ê®Æ, ¦]¬° {\ttfamily nanosleep()} ¨ç¦¡
´£¨Ñ¤F¤ñ¸û©ú½Tªº¨Ï¥Î¤èªk.
\item ±N¤º®eÂà´«¦¨ Linuxdoc-SGML ®æ¦¡, ¨Ã¥B­«·s§@¤F¨Ç³\ªº½s±Æ.
\item ¹ï«Ü¦h¦a¤è§@¤F¨Ç³\ªº¸É­z»P­×¥¿.
\end{itemize}







\section{¦p¦ó¦b C »y¨¥¤U¨Ï¥Î I/O °ð}


\subsection{¥¿³Wªº¤èªk}

¥Î¨Ó¦s¨ú I/O °ðªº±`¦¡ (Routine) ³£©ñ¦bÀÉ®× {\ttfamily /usr/include/asm/io.h} ¸Ì
(©Î©ñ¦b®Ö¤ß­ì©l½Xµ{¦¡¶°ªº {\ttfamily linux/include/asm-i386/io.h} ÀÉ®×¸Ì).
³o¨Ç±`¦¡¬O¥H³æ¦æ¥¨¶° (inline macros) ªº¤è¦¡¼g¦¨ªº, ©Ò¥H¨Ï¥Î®É¥u­n¥H
{\ttfamily \#include $<$asm/io.h$>$} ªº¤è¦¡¤Þ¥Î´N°÷¤F; ¤£»Ý­nªþ¥[¥ô¦ó¨ç¦¡À]
(libraries).

Ä¶ª`: ±`¦¡(Routine) ³q±`¬O«ü¨t²Î©I¥s(System Call)»P¨ç¦¡(Function)ªºÁ`ºÙ.

¦]¬° gcc (¦Ü¤Ö¥X²{¦b 2.7.2.3 ©M¥H«eªºª©¥») ¥H¤Î egcs (©Ò¦³ªºª©¥») ªº­­¨î,
§A¦b½sÄ¶¥ô¦ó¨Ï¥Î¨ì³o¨Ç±`¦¡ªº­ì©l½X®É {\itshape ¥²¶·\/} ¥´¶}³Ì¨Î¤Æ¿ï¶µ
({\ttfamily gcc -O1} ©Î¸û°ª¼h¦¸ªº), ©ÎªÌ¬O¦b°µ {\ttfamily \#include $<$asm/io.h$>$} 
³o­Ó°Ê§@«e¨Ï¥Î {\ttfamily \#define extern} ±N extern ©w¸q¦¨ªÅ¥Õ.

¬°¤F°£¿ùªº¥Øªº, §A½sÄ¶®É¥i¥H¨Ï¥Î {\ttfamily gcc -g -O} (¦Ü¤Ö²{¦bªº gcc ª©¥»¬O³o¼Ë),
¦ý¬O³Ì¨Î¤Æ¤§«á¦³®É¥i¯à·|Åý°£¿ù¾¹ (debugger) ªº¦æ¬°ÅÜªº¦³ÂI©_©Ç. 
¦pªG³o­Óª¬ªp¹ï§A¦Ó¨¥¬O­Ó§xÂZ, §A¥i¥H±N©Ò¦³¨Ï¥Î¨ì I/O 
°ðªº±`¦¡¶°¤¤©ñ¦b¤@­ÓÀÉ®×¸Ì¨Ã¥u¦b½sÄ¶¸ÓÀÉ®×®ÉÅ×¥´¶}³Ì¨Î¤Æ¿ï¶µ.

¦b§A¦s¨ú¥ô¦ó I/O °ð¤§«e, §A¥²¶·Åý§Aªºµ{¦¡¦³¦p¦¹°µªºÅv­­. ­n¹F¦¨³o­Ó¥Øªº
§A¥i¥H¦b§Aªºµ{¦¡¤@¶}©lªº¦a¤è (¦ý¬O­n¦b¥ô¦ó I/O °ð¦s¨ú°Ê§@¤§«e) ©I¥s 
{\ttfamily ioperm()} ³o­Ó¨ç¦¡ (¸Ó¨ç¦¡³Q«Å§i©óÀÉ®× {\ttfamily unistd.h} , ¨Ã¥B³Q©w¸q¦b
®Ö¤ß¤¤). ¨Ï¥Î»yªk¬O {\ttfamily ioperm(from, num, turn\_on)},
¨ä¤¤ {\ttfamily from} ¬O²Ä¤@­Ó¤¹³\¦s¨úªº I/O °ð¦ì§}, {\ttfamily num} ¬O±µµÛ³sÄò¦s¨ú
I/O °ð¦ì§}ªº¼Æ¥Ø. ¨Ò¦p, {\ttfamily ioperm(0x300, 5, 1)} ªº·N«ä´N¬O»¡¤¹³\¦s¨ú°ð
0x300 ¨ì 0x304 (¤@¦@¤­­Ó°ð¦ì§}). ¦Ó³Ì«á¤@­Ó°Ñ¼Æ¬O¤@­Ó¥¬ªL¥N¼Æ­È¥Î¨Ó«ü©w¬O§_
µ¹¤©µ{¦¡¦s¨ú I/O °ðªºÅv­­ (true (1)) ©Î¬O°£¥h¦s¨úªºÅv­­ (false (0)). §A
¥i¥H¦h¦¸©I¥s¨ç¦¡ {\ttfamily ioperm()} ¥H«K¨Ï¥Î¦h­Ó¤£³sÄòªº°ð¦ì§}. ¦Ü©ó»yªkªº²Ó¸`½Ð
°Ñ¦Ò {\ttfamily ioperm(2)} ªº¨Ï¥Î»¡©ú¤å¥ó.

§Aªºµ{¦¡¥²¶·¾Ö¦³ root ªºÅv­­Å×¯à©I¥s¨ç¦¡ {\ttfamily ioperm()} ; ©Ò¥H§A¦pªG¤£¬O¥H
root ªº¨­¥÷°õ¦æ¸Óµ{¦¡, ´N¬O±o±N¸Óµ{¦¡ setuid ¦¨ root. ·í§A©I¥s¹L¨ç¦¡ {\ttfamily ioperm()}
¥´¶} I/O °ðªº¦s¨úÅv­­«á§A«K¥i¥H®³±¼ root ªºÅv­­. ¦b§Aªºµ{¦¡µ²§ô¤§«á¨Ã¤£¯S§O
­n¨D§A¥H {\ttfamily ioperm(..., 0)} ³o­Ó¤è¦¡®³±¼ I/O °ðªº¦s¨úÅv­­; ¦]¬°·í§Aªºµ{¦¡
°õ¦æ§¹²¦¤§«á³o­Ó°Ê§@·|¦Û°Ê§¹¦¨.

©I¥s¨ç¦¡ {\ttfamily setuid()} ±N¥Ø«e°õ¦æµ{¦¡ªº¦³®Ä¨Ï¥ÎªÌÃÑ§O½X (ID) ³]©w¦¨«D 
root ªº¨Ï¥ÎªÌ¨Ã¤£¼vÅT¨ä¥ý«e¥H {\ttfamily ioperm()} ªº¤è¦¡©Ò¨ú±oªº I/O °ð¦s¨úÅv­­,
¦ý¬O©I¥s¨ç¦¡ {\ttfamily fork()} ªº¤è¦¡«o·|¦³©Ò¼vÅT (ÁöµM¤÷¦æµ{ (parent process) 
«O¦³¦s¨úÅv­­, ¦ý¬O¤l¦æµ{ (child process) «oµLªk¨ú±o¦s¨úÅv­­). 

¨ç¦¡ {\ttfamily ioperm()} ¥u¯àÅý§A¨ú±o°ð¦ì§} 0x000 ¨ì 0x3ff ªº¦s¨úÅv­­; ¦Ü©ó
¸û°ª¦ì§}ªº°ð, §A±o¨Ï¥Î¨ç¦¡ {\ttfamily iopl()}  (¸Ó¨ç¦¡Åý§A¤@¦¸¥i¥H¦s¨ú©Ò¦³ªº°ð¦ì§}).
±NÅv­­µ¥¯Å°Ñ¼Æ­È³]¬° 3 (¨Ò¦p, {\ttfamily iopl(3)}) ¥H«K§Aªºµ{¦¡¯à°÷¦s¨ú {\itshape ©Ò¦³ªº\/}
I/O °ð (¦]¦¹­n¤p¤ß --- ¦pªG¦s¨ú¨ì¿ù»~ªº°ð¦ì§}±N¹ï§Aªº¹q¸£³y¦¨¦UºØ¤£¥i¹w´Áªº·l®`. 
¦P¼Ë¦a, ©I¥s¨ç¦¡ {\ttfamily iopl()} §A±o¾Ö¦³ root ªºÅv­­.¦Ü©ó»yªkªº²Ó¸`½Ð°Ñ¦Ò 
{\ttfamily iopl(2)} ªº¨Ï¥Î»¡©ú¤å¥ó.

±µµÛ, §Ú­Ì¨Ó¹ê»Ú¦a¦s¨ú I/O °ð... ­n±q¬Y­Ó°ð¦ì§}¿é¤J¤@­Ó byte (8 ­Ó bits)
ªº¸ê®Æ, §A±o©I¥s¨ç¦¡ {\ttfamily inb(port)} , ¸Ó¨ç¦¡·|¶Ç¦^©Ò¨ú±oªº¤@­Ó byte ªº¸ê®Æ.
­n¿é¥X¤@­Ó  byte ªº¸ê®Æ, §A±o©I¥s¨ç¦¡ {\ttfamily outb(value, port)}  (½Ð°O¦í°Ñ¼Æªº¦¸§Ç).
­n±q¬Y¤G­Ó°ð¦ì§} {\ttfamily x} ©M {\ttfamily x+1} (¤G­Ó byte ²Õ¦¨¤@­Ó word, ¬G¨Ï¥Î²Õ¦X»y¨¥
«ü¥O {\ttfamily inw}) ¿é¤J¤@­Ó word (16 ­Ó bits) ªº¸ê®Æ, §A±o©I¥s¨ç¦¡ {\ttfamily inw(x)} ;
­n¿é¥X¤@­Ó word ªº¸ê®Æ¨ì¤G­Ó°ð¦ì§}, §A±o©I¥s¨ç¦¡ {\ttfamily outw(value, x)} .
¦pªG§A¤£½T©w¨Ï¥Î¨º­Ó°ð«ü¥O (byte ©Î word), §A¤j·§¶·­n {\ttfamily inb()} »P {\ttfamily outb()}
³o¤G­Ó°ð«ü¥O --- ¦]¬°¤j¦h¼Æªº¸Ë¸m³£¬O±Ä¥Î byte ¤j¤pªº°ð¦s¨ú¤è¦¡¨Ó³]­pªº. 
ª`·N©Ò¦³ªº°ð¦s¨ú«ü¥O³£¦Ü¤Ö»Ý­n¤j¬ù¤@·L¬íªº®É¶¡¨Ó°õ¦æ.

¦pªG§A¨Ï¥Îªº¬O {\ttfamily inb\_p()}, {\ttfamily outb\_p()}, {\ttfamily inw\_p()}, ¥H¤Î {\ttfamily outw\_p()}
µ¥¥¨¶°«ü¥O, ¦b§A¹ï°ð¦ì§@§}¦s¨ú°Ê§@¤§«á¥u»Ý«Üµuªº(¤j¬ù¤@·L¬í)©µ¿ð®É¶¡´N¥i¥H§¹¦¨;
§A¤]¥i¥HÅý©µ¿ð®É¶¡ÅÜ¦¨¤j¬ù¥|·L¬í¤èªk¬O¦b¨Ï¥Î {\ttfamily \#include $<$asm/io.h$>$}
¤§«e¨Ï¥Î {\ttfamily \#define REALLY\_SLOW\_IO}. ³o¨Ç¥¨¶°«ü¥O³q±` (°£«D§A¨Ï¥Îªº¬O
{\ttfamily \#define SLOW\_IO\_BY\_JUMPING}, ³o­Ó¤èªk¥i¯à¸û¤£·Ç½T) ·|§Q¥Î¿é¥X¸ê®Æ¨ì°ð¦ì§} 
0x80 ¥H«K¹F¨ì©µ¿ð®É¶¡ªº¥Øªº, ©Ò¥H§A±o¥ý¥H¨ç¦¡ {\ttfamily ioperm()} ¨ú±o°ð¦ì§} 0x80
ªº¨Ï¥ÎÅv­­ (¿é¥X¸ê®Æ¨ì°ð¦ì§} 0x80 ¤£À³¸Ó·|¹ï¨t²Îªº¨ä¥L¨ä¥L³¡¤À³y¦¨¼vÅT). ¦Ü©ó
¨ä¥L³q¥Îªº©µ¿ð®É¶¡ªº¤èªk, ½ÐÄ~ÄòÅª¤U¥h. 

{\ttfamily ioperm(2)}, {\ttfamily iopl(2)} µ¥¨ç¦¡, ©M¤W­±©Ò­z¤Îªº¥¨¶°«ü¥Oªº¨Ï¥Î»¡©ú·|¦¬¿ý¦b
³Ìªñ¥Xª©ªº Linux ¨Ï¥Î»¡©ú¤å¥ó¶°¤¤.




\subsection{¥t¤@­Ó´À¥Nªº¤èªk: {\ttfamily /dev/port}}

¥t¤@­Ó¦s¨ú I/O °ðªº¤èªk¬O¥H¨ç¦¡ {\ttfamily open()} ¶}±ÒÀÉ®× {\ttfamily /dev/port} 
(¤@­Ó¦r¤¸¸Ë¸m,¥D­n¸Ë¸m½s¸¹¬° 1, ¦¸­n¸Ë¸m½s¸¹¬° 4) ¥H«K°õ¦æÅª¥B/©Î¼gªº°Ê§@
(ª`·N¼Ð·Ç¿é¥X¤J (stdio) ¨ç¦¡ {\ttfamily f*()} ¦³¤º³¡ªº½w½Ä (buffering), ©Ò¥H­nÁ×§K¨Ï¥Î).
±µµÛ¨Ï¥Î {\ttfamily lseek()} ¨ç¦¡¥H«K¦b¸Ó¦r¤¸¸Ë¸mÀÉ®×¤¤§ä¨ì¬Y­Ó byte ¸ê®Æªº¥¿½T¦ì¸m
(ÀÉ®×¦ì¸m 0 = °ð¦ì§} 0x00, ÀÉ®×¦ì¸m 1 = °ð¦ì§} 0x01, ¥H¦¹Ãþ±À), µM«á§A¥i¥H¨Ï¥Î
{\ttfamily read()} ©Î {\ttfamily write()} ¨ç¦¡¹ï¬Y­Ó°ð¦ì§}°µÅª©Î¼g¤@­Ó byte ©Î word ¸ê®Æªº°Ê§@.

³o­Ó´À¥Nªº¤èªk´N¬O¦b§Aªºµ{¦¡¸Ì¨Ï¥Î read/write ¨ç¦¡¨Ó¦s¨ú {\ttfamily /dev/port} 
¦r¤¸¸Ë¸mÀÉ®×. ³o­Ó¤èªkªº°õ¦æ³t«×©Î³\¤ñ«e­±©ÒÁ¿ªº¤@¯ë¤èªkÁÙºC, ¦ý¬O¤£»Ý­n½sÄ¶¾¹
ªº³Ì¨Î¤Æ¥\¯à¤]¤£»Ý­n¨Ï¥Î¨ç¦¡ {\ttfamily ioperm()} . ¦pªG§A¤¹³\«D root ¨Ï¥ÎªÌ©Î¸s²Õ¦s¨ú
{\ttfamily /dev/port} ¦r¤¸³]¸Ë¸m®×, ¾Þ§@®É´N¤£»Ý¾Ö¦³ root Åv­­ -- ¦ý¬O¹ï©ó¨t²Î¦w¥þ¦Ó¨¥
¬O­Ó«D±`ÁV¿|ªº¨Æ±¡, ¦]¬°¥L¥i¯à¶Ë®`¨ì§Aªº¨t²Î, ©Î³\·|¦³¤H¦]¦Ó¨úªº root ªºÅv­­,
§Q¥Î {\ttfamily /dev/port} ¦r¤¸¸Ë¸mÀÉ®×ª½±µ¦s¨úµwºÐ, ºô¸ô¥d, µ¥³]³Æ.




\section{µwÅé¤¤Â_ (IRQs) »P DMA ¦s¨ú}

§Aªºµ{¦¡¦pªG¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤U°õ¦æ¤£¥i¥Hª½±µ¨Ï¥ÎµwÅé¤¤Â_ (IRQs) ©Î DMA. 
§A¥²»Ý¼¶¼g¤@­Ó®Ö¤ßÅX°Êµ{¦¡; ¬ÛÃöªº²Ó¸`½Ð°Ñ¦Òºô­¶
\nameurl{http://www.redhat.com:8080/HyperNews/get/khg.html}{The Linux Kernel Hacker's Guide} ¥H¤Î®³®Ö¤ßµ{¦¡­ì©l½X¨Ó·í½d¨Ò. 

¤]´N¬O»¡, §A¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤¤©Ò¼gªºµ{¦¡µLªk§í¨îµwÅé¤¤Â_ªº²£¥Í.




\section{°ªºë½Tªº®É§Ç}


\subsection{©µ¿ð®É¶¡}

­º¥ý, §Ú·|»¡¤£«OÃÒ§A¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤¤°õ¦æªº¦æµ{ (process) 
¯à°÷ºë½T¦a±±¨î®É§Ç¦]¬° Linux ¬O­Ó¦h¤uªº§@·~Àô¹Ò. §A¦b°õ¦æ¤¤ªº¦æµ{ (process) 
ÀH®É·|¦]¬°¦UºØ­ì¦]³Q¼È°±¤j¬ù 10 ²@¬í¨ì¼Æ¬í (¦b¨t²Î­t²ü«D±`°ªªº®É­Ô). µM¦Ó, 
¹ï©ó¤j¦h¼Æ¨Ï¥Î I/O °ðªºÀ³¥Î¦Ó¨¥, ³o­Ó©µ¿ð®É¶¡¹ê»Ú¤Wºâ¤£¤F¤°»ò. ­nÁYµu©µ¿ð®É¶¡,
§A±o¨Ï¥Î¨ç¦¡ nice ±N§A¦b°õ¦æ¤¤ªº¦æµ{ (process ) ³]©w¦¨°ªÀu¥ýÅv(½Ð°Ñ¦Ò 
{\ttfamily nice(2)} ¨Ï¥Î»¡©ú¤å¥ó) ©Î¨Ï¥Î§Y®É±Æµ{ªk (real-time scheduling) (½Ð¬Ý¤U­±). 

¦pªG§A·QÀò±o¤ñ¦b¤@¯ë¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤¤°õ¦æªº¦æµ{ (process) 
ÁÙ­nºë½Tªº®É§Ç, ¦³¤@¨Ç¤èªk¥i¥HÅý§A¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) 
¤¤°µ¨ì `§Y®É' ±Æµ{ªº¤ä´©. Linux 2.x ª©¥»ªº®Ö¤ß¤¤¦³³nÅé¤è¦¡ªº§Y®É±Æµ{¤ä´©; 
¸Ô²Óªº»¡©ú½Ð°Ñ¦Ò {\ttfamily sched\_setscheduler(2)} ¨Ï¥Î»¡©ú¤å¥ó. 
¦³¤@­Ó¯S®íªº®Ö¤ß¤ä´©µwÅéªº§Y®É±Æµ{; ¸Ô²Óªº¸ê°T½Ð°Ñ¦Òºô­¶ \nameurl{http://luz.cs.nmt.edu/rtlinux/}{} 




\subsubsection{¥ð®§¤¤ (Sleeping) : {\ttfamily sleep()} »P {\ttfamily usleep()}}

²{¦b, Åý§Ú­Ì¶}©l¸ûÂ²³æªº®É§Ç¨ç¦¡©I¥s. ·Q­n©µ¿ð¼Æ¬íªº®É¶¡, ³Ì¨Îªº¤èªk¤j·§
¬O¨Ï¥Î¨ç¦¡ {\ttfamily sleep()} . ·Q­n©µ¿ð¦Ü¤Ö¼Æ¤Q²@¬íªº®É¶¡ (10 ms ¦ü¥G¤w¬O³Ìµuªº
©µ¿ð®É¶¡¤F), ¨ç¦¡ {\ttfamily usleep()} À³¸Ó¥i¥H¨Ï¥Î. ³o¨Ç¨ç¦¡¬OÅý¥X CPU ªº¨Ï¥ÎÅv
µ¹¨ä¥L·Q­n°õ¦æªº¦æµ{ (processes)  (``¦Û¤v¥ð®§¥h¤F''), ©Ò¥H¨S¦³®ö¶O±¼ CPU 
ªº®É¶¡. ²Ó¸`½Ð°Ñ¦Ò {\ttfamily sleep(3)} »P {\ttfamily usleep(3)} ªº»¡©ú¤å¥ó.

¦pªGÅý¥X CPU ªº¨Ï¥ÎÅv¦]¦Ó¨Ï±o®É¶¡©µ¿ð¤F¤j¬ù 50 ²@¬í (³o¨ú¨M©ó³B²z¾¹»P¾÷¾¹ªº³t«×, 
¥H¤Î¨t²Îªº­t²ü), ´N®ö¶O±¼ CPU ¤Ó¦hªº®É¶¡, ¦]¬° Linux ªº±Æµ{¾¹ (scheduler) 
(³æ´N x86 ¬[ºc¦Ó¨¥) ¦b±N±±¨îÅvµoÁÙµ¹§Aªº¦æµ{ (process) ¤§«e³q±`¦Ü¤Ö­nªá¶O 
10-30 ²@¬íªº®É¶¡. ¦]¦¹, µu®É¶¡ªº©µ¿ð, ¨Ï¥Î¨ç¦¡ {\ttfamily usleep(3)} 
©Ò±o¨ìªº©µ¿ðµ²ªG³q±`·|¤j©ó§A¦b°Ñ¼Æ©Ò«ü©wªº­È, ¤j¬ù¦Ü¤Ö¦³ 10 ms. 






\subsubsection{{\ttfamily nanosleep()}}

¦b Linux 2.0.x ¤@¨t¦Cªº®Ö¤ßµo¦æª©¥»¤¤, ¦³¤@­Ó·sªº¨t²Î©I¥s (system call),
{\ttfamily nanosleep()} (½Ð°Ñ¦Ò {\ttfamily nanosleep(2)} ªº»¡©ú¤å¥ó), ¥LÅý§A¯à°÷
¥ð®§©Î©µ¿ð¤@­Óµuªº®É¶¡ (¼Æ·L¬í©Î§ó¦h).

¦pªG©µ¿ðªº®É¶¡ $<$= 2 ms, ­Y(¥B°ß­Y)§A°õ¦æ¤¤ªº¦æµ{ (process) ³]©w¤F³nÅéªº§Y®É
±Æµ{ (´N¬O¨Ï¥Î¨ç¦¡ tt/sched\_setscheduler()/), ©I¥s¨ç¦¡ {\ttfamily nanosleep()}  ®É
¤£¬O¨Ï¥Î¤@­Ó¦£¸L°j°é¨Ó©µ¿ð®É¶¡; ´N¬O·|¹³¨ç¦¡ {\ttfamily usleep()} ¤@¼ËÅý¥X CPU
ªº¨Ï¥ÎÅv¥ð®§¥h¤F.

³o­Ó¦£¸L°j°é¨Ï¥Î¨ç¦¡ {\ttfamily udelay()} (¤@­ÓÅX°Êµ{¦¡±`·|¥Î¨ìªº®Ö¤ß¤º³¡ªº¨ç¦¡)
¨Ó¹F¦¨, ¨Ã¥B¨Ï¥Î BogoMips ­È (BogoMips ¥i¥H·Ç½T¶q´ú³oÃþ¦£¸L°j°éªº³t«×)
¨Ó­pºâ°j°é©µ¿ðªº®É¶¡ªø«×. ¨ä¦p¦ó°Ê§@ªº²Ó¸`½Ð°Ñ¦Ò 
{\ttfamily /usr/include/asm/delay.h}).




\subsubsection{¨Ï¥Î I/O °ð¨Ó©µ¿ð®É¶¡}

¥t¤@­Ó©µ¿ð¼Æ·L¬íªº¤èªk¬O¨Ï¥Î I/O °ð. ´N¬O±q°ð¦ì§} 0x80 ¿é¤J©Î¿é¥X¥ô¦ó byte 
ªº¸ê®Æ (½Ð°Ñ¦Ò«e­±) µ¥«Ýªº®É¶¡À³¸Ó´X¥G¥u­n 1 ·L¬í³o­n¬Ý§Aªº³B²z¾¹ªº«¬§O»P³t«×.
¦pªG­n©µ¿ð¼Æ·L¬íªº®É¶¡§A¥i¥H±N³o­Ó°Ê§@¦h°µ´X¦¸. ¦b¥ô¦ó¼Ð·Çªº¾÷¾¹¤W¿é¥X¸ê®Æ¨ì¸Ó
°ð¦ì§}À³¸Ó¤£·|¦³¤£¨}ªº«áªGÅ×¹ï (¦Ó¥B¦³¨Ç®Ö¤ßªº³]³ÆÅX°Êµ{¦¡¤]¦b¨Ï¥Î¥L).
{\ttfamily $\{$in$|$out$\}$[bw]\_p()} µ¥¨ç¦¡´N¬O¨Ï¥Î³o­Ó¤èªk¨Ó²£¥Í®É¶¡©µ¿ðªº
(½Ð°Ñ¦ÒÀÉ®× {\ttfamily asm/io.h}).

¹ê»Ú¤W, ¤@­Ó¨Ï¥Î¨ì°ð¦ì§}½d³ò¬° 0-0x3ff ªº I/O °ð«ü¥O´X¥G¥u­n 1 ·L¬íªº®É¶¡,
©Ò¥H¦pªG§A­n¦p¦¹°µ, ¨Ò¦p, ª½±µ¨Ï¥Î¨Ã¦C°ð, ¥u­n¥[¤W´X­Ó {\ttfamily inb()} ¨ç¦¡±q¸Ó
°ð¦ì§}½d³òÅª¤J byte ªº¸ê®Æ§Y¥i.




\subsubsection{¨Ï¥Î²Õ¦X»y¨¥¨Ó©µ¿ð®É¶¡}

¦pªG§Aª¾¹D°õ¦æµ{¦¡©Ò¦b¾÷¾¹ªº³B²z¾¹«¬§O»P®ÉÄÁ³t«×, 
§A¥i¥H°õ¦æ¬Y¨Ç²Õ¦X»y¨¥«ü¥O¥H«KÀò±o¸ûµuªº©µ¿ð®É¶¡ (¦ý¬O°O¦í, 
§A¦b°õ¦æ¤¤ªº¦æµ{ (process) ÀH®É·|³Q¼È°±,  ©Ò¥H¦³®É©µ¿ðªº®É¶¡·|¤ñ¹ê»Úªø). 
¦p¤U­±ªºªí®æ©Ò¥Ü, ¤º³¡³B²z¾¹ªº³t«×¨M©w¤F©Ò­n¨Ï¥Îªº®ÉÄÁ©P´Á¼Æ;
¦p, ¤@­Ó 50 MHz ªº³B²z¾¹ (486DX-50 ©Î 486DX2-50), ¤@­Ó®ÉÄÁ©P´Á­nªá¶O 1/50000000
¬í (=200 ©`¬í).

\begin{tscreen}
\begin{verbatim}
«ü¥O          i386 ®ÉÄÁ©P´Á¼Æ       i486 ®ÉÄÁ©P´Á¼Æ
nop                   3                   1
xchg %ax,%ax          3                   3
or %ax,%ax            2                   1
mov %ax,%ax           2                   1
add %ax,0             2                   1
\end{verbatim}
\end{tscreen}


(¹ï¤£°_, §Ú¤£ª¾¹D Pentiums ªº¸ê®Æ, ©Î³\»P i486 ±µªñ§a. §ÚµLªk¦b i386 
ªº¸ê®Æ¤W§ä¨ì¥uªá¶O¤@­Ó®ÉÄÁ©P´Áªº«ü¥O. ¦pªG¯à°÷´N½Ð¨Ï¥Îªá¶O¤@­Ó®ÉÄÁ©P´Áªº«ü¥O,
­n¤£µM´N¨Ï¥ÎºÞ½u§Þ³Nªº·s¦¡³B²z¾¹¤]¬O¥i¥HÁYµu®É¶¡ªº.)

¤W­±ªºªí®æ¤¤«ü¥O {\ttfamily nop} »P {\ttfamily xchg} À³¸Ó¤£·|¦³¤£¨}ªº«áªG. «ü¥O³Ì«á¥i¯à·|
§ïÅÜºX¸¹¼È¦s¾¹ªº¤º®e, ¦ý¬O³o¨SÃö«Y¦]¬° gcc ·|³B²z. «ü¥O {\ttfamily nop} ¬O­Ó¦nªº¿ï¾Ü.

·Q­n¦b§Aªºµ{¦¡¤¤¨Ï¥Î¨ì³o¨Ç«ü¥O, §A±o¨Ï¥Î {\ttfamily asm({\tt\char`\"}instruction{\tt\char`\"})}.
«ü¥Oªº»yªk´N¦p¦P¤W­±ªí®æªº¥Îªk; ¦pªG§A·Q­n¦b³æ¤@ªº {\ttfamily asm()} ±Ô­z¤¤¨Ï¥Î¦h­Ó«ü¥O,
¥i¥H¨Ï¥Î¤À¸¹±N¥L­Ì¹j¶}. ¨Ò¦p,
{\ttfamily asm({\tt\char`\"}nop ; nop ; nop ; nop{\tt\char`\"})} ·|°õ¦æ¥|­Ó {\ttfamily nop} «ü¥O, 
¦b i486 ©Î Pentium ³B²z¾¹¤¤·|©µ¿ð¥|­Ó®ÉÄÁ©P´Á (©Î¬O i386 ·|©µ¿ð 12 ­Ó®ÉÄÁ©P´Á).

gcc ·|±N {\ttfamily asm()} Â½Ä¶¦¨³æ¦æ²Õ¦X»y¨¥µ{¦¡½X, ©Ò¥H¤£·|¦³©I¥s¨ç¦¡ªº­t²ü.

¦b Intel x86 ¬[ºc¤¤¤£¥i¯à¦³¤ñ¤@­Ó®ÉÄÁ©P´ÁÁÙµuªº®É¶¡©µ¿ð.




\subsubsection{¦b Pentiums ³B²z¾¹¤W¨Ï¥Î¨ç¦¡ {\ttfamily rdtsc} }

¹ï©ó Pentiums ³B²z¾¹¦Ó¨¥, §A¥i¥H¨Ï¥Î¤U­±ªº C »y¨¥µ{¦¡½X¨Ó¨ú±o¦Û±q¤W¦¸­«·s¶}¾÷
¨ì²{¦b¸g¹L¤F¦h¤Ö­Ó®ÉÄÁ©P´Á:

\begin{tscreen}
\par
\addvspace{\medskipamount}
\nopagebreak\hrule
\begin{verbatim}
   extern __inline__ unsigned long long int rdtsc()
   {
     unsigned long long int x;
     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
     return x;
   }
\end{verbatim} 
\nopagebreak\hrule 
\addvspace{\medskipamount}
\end{tscreen}


§A¥i¥H¸ß°Ý°Ñ¦Ò¦¹­È¥H«K©µ¿ð§A·Q­nªº®ÉÄÁ©P´Á¼Æ.




\subsection{®É¶¡ªº¶q´ú}

·Q­n®É¶¡ºë½T¨ì¤@¬íÄÁ, ¨Ï¥Î¨ç¦¡ {\ttfamily time()} ©Î³\¬O³ÌÂ²³æªº¤èªk.
·Q­n®É¶¡§óºë½T, ¨ç¦¡ {\ttfamily gettimeofday()} ¤j¬ù¥i¥Hºë½T¨ì·L¬í
(¦ý¬O¦p«e©Ò­z·|¨ü¨ì CPU ±Æµ{ªº¼vÅT). ¦Ü©ó Pentiums ³B²z¾¹,
¨Ï¥Î¤W­±ªºµ{¦¡½X¤ùÂ_´N¥i¥Hºë½T¨ì¤@­Ó®ÉÄÁ©P´Á.

¦pªG§A­n§A°õ¦æ¤¤ªº¦æµ{ (process) ¦b¤@¬q®É¶¡¨ì¤F¤§«á¯à°÷³Q³qª¾ (get a signal), 
§A±o¨Ï¥Î¨ç¦¡ {\ttfamily setitimer()} ©Î {\ttfamily alarm()} . 
²Ó¸`½Ð°Ñ¦Ò¨ç¦¡ªº¨Ï¥Î»¡©ú¤å¥ó.




\section{¨Ï¥Î¨ä¥Lµ{¦¡»y¨¥}

¤W­±ªº»¡©ú¶°¤¤¦b C µ{¦¡»y¨¥. ¥LÀ³¸Ó¥i¥Hª½±µÀ³¥Î¦b C++ ¤Î Objective C ¤§¤W.
¦Ü©ó²Õ¦X»y¨¥³¡¤À, ÁöµM§A¥²¶·¥ý¦b C »y¨¥¤¤©I¥s¨ç¦¡ {\ttfamily ioperm()} ©Î {\ttfamily iopl()} ,
¦ý¬O¤§«á§A´N¥i¥Hª½±µ¨Ï¥Î I/O °ðÅª¼g«ü¥O.

¦Ü©ó¨ä¥Lµ{¦¡»y¨¥, °£«D§A¥i¥H¦b¸Óµ{¦¡»y¨¥¤¤´¡¤J³æ¦æ²Õ¦X»y¨¥©Î 
C »y¨¥¤§µ{¦¡½X©ÎªÌ¨Ï¥Î¤W­±©Ò»¡ªº¨t²Î©I¥s, §_«h­Ë¤£¦p¼¶¼g¤@­Ó¤º§t¦³¦s¨ú 
I/O °ð©Î©µ¿ð®É¶¡©Ò¥²»Ý¨ç¦¡¤§Â²³æªº C ­ì©lµ{¦¡½X©Î³\ÁÙ¤ñ¸û®e©ö, 
½sÄ¶¤§«á¦A»P§Aªºµ{¦¡Ãìµ². 
­n¤£µM´N¬O¨Ï¥Î«e­±©Ò»¡ªº {\ttfamily /dev/port} ¦r¤¸¸Ë¸mÀÉ®×.




\section{¤@¨Ç¦³¥Îªº I/O °ð}

¥»¸`´£¨Ñ¤@¨Ç±`¥Î I/O °ðªºµ{¦¡¼¶¼g¸ê°T³o¨Ç³£¬O¥i¥Hª½±µ®³¨Ó¥Îªº¤@¯ë¥Øªº
TTL (©Î CMOS) ÅÞ¿è¦ì·Çªº I/O °ð.

¦pªG§A­n«ö·Ó¨ä­ì©lªº³]­p¥Øªº¨Ó¨Ï¥Î³o¨Ç©Î¨ä¥L±`¥ÎªºI/O °ð 
(¨Ò¦p, ±±¨î¤@¯ëªº¦Lªí¾÷©Î¼Æ¾Ú¾÷), §AÀ³¸Ó·|¨Ï¥Î²{¦¨ªº¸Ë¸mÅX°Êµ{¦¡ 
(¥L³q±`³Q§t¦b®Ö¤ß¤¤) ¦Ó¤£·|¦p¥»¤å©Ò»¡¦a¥h¼¶¼g I/O °ðµ{¦¡.
¥»¸`¥D­n¬O´£¨Ñµ¹¨º¨Ç·Q­n±N LCD Åã¥Ü¾¹, ¨B¶i°¨¹F, ©Î¬O¨ä¥L°Ó·~¹q¤l²£«~
³s±µ¨ì PC ¼Ð·Ç I/O °ðªº¤H.

¦pªG§A·Q­n±±¨î¤j²³¥«³õ©Ò³c½æªº¸Ë¸m¹³¬O±½´y¾¹ (¤w¸g¦b¥«³õ³c½æ¤F¤@¬q´Á¶¡),
¥h§ä¬Ý¬Ý¬O§_¦³²{¦¨ªº Linux ¸Ë¸mÅX°Êµ{¦¡.
ºô­¶ \nameurl{http://sunsite.unc.edu/pub/Linux/docs/HOWTO/Hardware-HOWTO}{Hardware-HOWTO} ¬O­Ó¦nªº°Ñ¦Ò°_ÂI.

¦Ü©ó·Q­nª¾¹D§ó¦h¦³Ãö¦p¦ó³s±µ¹q¤l¸Ë¸m¨ì¹q¸£(¥H¤Î¤@¯ëªº¹q¤l¾Ç­ì²z)ªº¬ÛÃö¸ê°T«hºô­¶
\nameurl{http://www.hut.fi/Misc/Electronics/}{} ¬O­Ó¦nªº¸ê®Æ¨Ó·½. 






\subsection{¨Ã¦C°ð (parallel port)}

¨Ã¦C°ðªº°ò¥»°ð¦ì§} (¥H¤UºÙ¤§¬° ``{\ttfamily BASE}'') ¤§©ó {\ttfamily /dev/lp0} 
¬O 0x3bc , ¤§©ó {\ttfamily /dev/lp1} ¬O 0x378 , ¤§©ó {\ttfamily /dev/lp2} ¬O 0x278 .
¦pªG§A¥u¬O·Q­n±±¨î¤@¨Ç¹³¬O¤@¯ë¦Lªí¾÷ªº°Ê§@, ¥i¥H°Ñ¦Òºô­¶ \nameurl{http://sunsite.unc.edu/pub/Linux/docs/HOWTO/Printing-HOWTO}{Printing-HOWTO}. 

°£¤F¤U­±§Y±N´y­zªº¼Ð·Ç¶È¿é¥X (output-only) ¼Ò¦¡, ¤j¦h¼Æªº¨Ã¦C°ð³£¦³ `ÂX¥Rªº'
Âù¦V (bidirectional) ¼Ò¦¡. ¦Ü©ó¸û·sªº ECP/EPP ¼Ò¦¡ (¥H¤Î¤@¯ëªº IEEE 1284 ¼Ð·Ç) °ð¤fªº¬ÛÃö¸ê®Æ,
¥i¥H°Ñ¦Òºô­¶ \nameurl{http://www.fapo.com/}{} ¥H¤Î \nameurl{http://www.senet.com.au/cpeacock/parallel.htm}{}.
¦]¬°¦b¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ¤¤ªºµ{¦¡µLªk¨Ï¥Î IRQs ©Î DMA, ·Q­n¨Ï¥Î ECP/EPP 
¼Ò¦¡§A©Î³\±o¼¶¼g¤@­Ó®Ö¤ßªº¸Ë¸mÅX°Êµ{¦¡; §Ú·QÀ³¸Ó¦³¤H¼g¤F³oÃþªº¸Ë¸mÅX°Êµ{¦¡, 
¦ý¬O¸Ô±¡§Ú¨Ã¤£ª¾¹D. 

°ð¦ì§} {\ttfamily BASE+0} (¸ê®Æ°ð) ¥Î¨Ó±±¨î¸ê®Æ°ðªº«H¸¹¦ì·Ç (D0 ¨ì D7 ¤À§O¥NªíµÛ 
bits 0 ¨ì 7, ¦ì·Çª¬ºA: 0 = §C¦ì·Ç (0 V), 1 = °ª¦ì·Ç (5 V)). 
¤@­Ó¼g¤J¸ê®Æ¨ì¸Ó°ðªº°Ê§@·|±N¸ê®Æ«H¸¹¦ì·Ç¬C¦í (latches) ¦b°ðªº¸}¦ì (pins) ¤W.
¤@­Ó±N¸Ó°ðªº¸ê®ÆÅª¥Xªº°Ê§@·|±N¤W¤@¦¸¥H¼Ð·Ç¶È¿é¥X (output-only) 
¼Ò¦¡©ÎÂX¥Rªº¼g¤J¼Ò¦¡©Ò¬C¦íªº¸ê®Æ«H¸¹¦ì·ÇÅª¦^, ©Î¬O¥HÂX¥RÅª¥X¼Ò¦¡ ±q¥t¥~¤@
­Ó¸Ë¸m±N¸}¦ì¤Wªº¸ê®Æ«H¸¹¦ì·ÇÅª¦^.

°ð¦ì§} {\ttfamily BASE+1} (ª¬ºA°ð) ¬O­Ó¶ÈÅª (read-only) ªº°ð, ·|±N¤U­±ªº¿é¤J«H¸¹¦ì·ÇÅª¦^:
\begin{itemize}
\item Bits 0 ©M 1 «O¯d¤£¥Î.
\item Bit 2 IRQ ªºª¬ºA (¤£¬O­Ó¸}¦ì (pin) , §Ú¤£ª¾¹D¥Lªº¤u§@­ì²z)
\item Bit 3 ERROR (1=°ª¦ì·Ç)
\item Bit 4 SLCT (1=°ª¦ì·Ç)
\item Bit 5 PE (1=°ª¦ì·Ç)
\item Bit 6 ACK (1=°ª¦ì·Ç)
\item Bit 7 -BUSY (0=°ª¦ì·Ç)
\end{itemize}

(§Ú¤£½T©w°ª§C¦ì·Çªº¹qÀ£ª¬ºA.)

°ð¦ì§} {\ttfamily BASE+2} (±±¨î°ð) ¬O­Ó¶È¼g (write-only) ªº°ð 
(¤@­Ó±N¸Ó°ðªº¸ê®ÆÅª¥Xªº°Ê§@¶È·|±N¤W¤@¦¸¼g¤Jªº¸ê®Æ«H¸¹¦ì·ÇÅª¦^), ¥Î¨Ó±±¨î¤U­±ªºª¬ºA«H¸¹:
\begin{itemize}
\item Bit 0 -STROBE (0=°ª¦ì·Ç)
\item Bit 1 AUTO\_FD\_XT (1=°ª¦ì·Ç)
\item Bit 2 -INIT (0=°ª¦ì·Ç)
\item Bit 3 SLCT\_IN (1=°ª¦ì·Ç)
\item Bit 4 ·í³Q³]©w¬° 1 ®É¤¹³\¨Ã¦C°ð²£¥Í IRQ «H¸¹ 
(µo¥Í¦b ACK ¸}¦ìªº¦ì·Ç¥Ñ§CÅÜ°ªªºÀþ¶¡)  
\item Bit 5 ¥Î¨Ó±±¨îÂX¥R¼Ò¦¡®É°ðªº¿é¥X¤J¤è¦V (0 = ¼g, 1 = Åª),
³o¬O­Ó¶È¼g (write-only) ªº°ð (¤@­Ó±N¸Ó°ðªº¸ê®ÆÅª¥Xªº°Ê§@¹ï¦¹ bit ¤@ÂI¥Î³B¤]¨S¦³).
\item Bits 6 and 7 «O¯d¤£¥Î.
\end{itemize}

(¦P¼Ë¦a, §Ú¤£½T©w°ª§C¦ì·Çªº¹qÀ£ª¬ºA.)

°ðªº¸}¦ì±Æ¦C (Pinout) ¤è¦¡ (¸Ó°ð¬O¤@­Ó 25 °¦¸} D ¦r§Î¥~´ß (D-shell) ªº¥ÀÀY³s±µ¾¹)
(i=¿é¤J, o=¿é¥X):
\begin{tscreen}
\begin{verbatim}
1io -STROBE, 2io D0, 3io D1, 4io D2, 5io D3, 6io D4, 7io D5, 8io D6,
9io D7, 10i ACK, 11i -BUSY, 12i PE, 13i SLCT, 14o AUTO_FD_XT,
15i ERROR, 16o -INIT, 17o SLCT_IN, 18-25 Ground
\end{verbatim}
\end{tscreen}


IBM ªº³W®æ¤å¥ó¤W»¡¸}¦ì 1, 14, 16, ©M 17 (±±¨î«H¸¹ªº¿é¥X) ±Ä¥Î¹q´¹Åéªº¶}¶°·¥
(open collector) ÅX°Ê¤è¦¡¥²»Ý¨Ï¥Î 4.7 ¥a¼Ú©i (kiloohm) ªº´£¤É¹qªý±µ¦Ü 
5 V ªº¹qÀ£ (¥i¬y¤J¹q¬y 20 mA, ¬y¥X¹q¬y 0.55 mA, °ª¦ì·Çªº¿é¥X¹qÀ£´N¬O 
5.0 V ´î¥h´£¤É¹qªýªº¹qÀ£). ³Ñ¤U¨Óªº¸}¦ì¥i¬y¤J¹q¬y 24 mA, ¬y¥X¹q¬y 15 mA, 
°ª¦ì·Çªº¿é¥X¹qÀ£³Ì¤p 2.4 V. §C¦ì·Çªº¿é¥X¹qÀ£¤GªÌ³£¬O³Ì¤j 0.5 V.
¨º¨Ç«D IBM ³W®æªº¨Ã¦C°ð©Î³\·|°¾Â÷³o­Ó¼Ð·Ç. §ó¦hªº¬ÛÃö¸ê®Æ½Ð°Ñ¦Òºô­¶
\nameurl{http://www.hut.fi/Misc/Electronics/circuits/lptpower.html}{}.

³Ì«á, µ¹§A¤@­ÓÄµ§i: ¯d¤ß±µ¦aªº°ÝÃD. §Ú´¿¸g¦b¹q¸£ÁÙ¬O¶}¾÷ªºª¬ªp´N¥h³s±µ¥L¦]¦Ó
§ËÃa¦n´X­Ó¨Ã¦C°ð. µo¥Í¤F³oºØ¨Æ±¡§A¥i¯à·|Ä±±oÁÙ¬O¤£­n±N¨Ã¦C°ð¾ã
¦X¨ì¥D¾÷ªO¸Ì­±¤ñ¸û¦n. (§A³q±`¥i¥H®³¤@¤ù«K©yªº¼Ð·Ç `multi-I/O' ¥d¦w¸Ë²Ä¤G­Ó
¨Ã¦C°ð; ¥u­n±N¨ä¥L¤£»Ý­nªº°ð°±¥Î, µM«á±N¥d¤ù¤W¨Ã¦C°ðªº°ð¦ì§}³]©w¦b
ªÅµÛªº¦ì§}§Y¥i. §A¤£»Ý¦b·N¨Ã¦C°ðªº IRQ ³]©w, ¦]¬°³q±`¤£·|³Q¥Î¨ì.)




\subsection{¹CÀ¸ (¾ÞÁa±ì) °ð (game port)}

¹CÀ¸°ðªº°ð¦ì§}½d³ò¬° 0x200-0x207. ·Q­n±±¨î¤@¯ëªº¾ÞÁa±ì, 
¦³¤@­Ó®Ö¤ß¼h¦¸ªº¾ÞÁa±ìÅX°Êµ{¦¡, ¥i°Ñ¦Òºô§} \nameurl{ftp://sunsite.unc.edu/pub/Linux/kernel/patches/}{},
ÀÉ¦W {\ttfamily joystick-*}.

°ðªº¸}¦ì±Æ¦C (Pinout) ¤è¦¡ (¸Ó°ð¬O¤@­Ó 15 °¦¸} D ¦r§Î¥~´ß (D-shell) ªº¥ÀÀY³s±µ¾¹):
\begin{itemize}
\item 1,8,9,15: +5 V (¹q·½)
\item 4,5,12: ±µ¦a
\item 2,7,10,14: ¤À§O¬O BA1, BA2, BB1, ©M BB2 µ¥¼Æ¦ì¿é¤J
\item 3,6,11,13: ¤À§O¬O AX, AY, BX, ©M BY µ¥``Ãþ¤ñ''¿é¤J
\end{itemize}


+5 V ªº¸}¦ì¦ü¥G³q±`·|³Qª½±µ³s±µ¨ì¥D¾÷ªOªº¹q·½½u¤W, ©Ò¥H¥LÀ³¸Ó¯à°÷´£¨Ñ¬Û·íªº¹q¤O,
³oÁÙ­n¬Ý©Ò¨Ï¥Î¥D¾÷ªO, ¹q·½¨Ñµ¹¾¹, ¥H¤Î¹CÀ¸°ðªºÃþ«¬.

¼Æ¦ì¿é¤J¥Î©ó¾ÞÁa±ìªº«ö¶s¥i¥HÅý§A³s±µ¤G­Ó¾ÞÁa±ìªº¥|­Ó«ö¶s (¾ÞÁa±ì A ©M ¾ÞÁa±ì B, 
¦U¦³¤G­Ó«ö¶s) ¨ì¹CÀ¸°ð¤]´N¬O¼Æ¦ì¿é¤Jªº¥|­Ó¸}¦ì. ¥L­ÌÀ³¸Ó¬O¤@¯ë TTL ¹qÀ£¦ì·Çªº¿é¤J,
§A¥i¥Hª½±µ±qª¬ºA°ð (°Ñ¦Ò¤U­±»¡©ú) Åª¥X¥L­Ìªº¦ì·Çª¬ºA. 
¤@­Ó¹ê»Úªº¾ÞÁa±ì¦b«ö¶s³QÀ£¤U®É·|¶Ç¦^§C¦ì·Ç (0 V) ª¬ºA§_«h´N¬O°ª¦ì·Ç 
(5V ¸g¥Ñ 1 Kohm ªº¹qªý³s±µ¨ì¹q·½¸}¦ì) ª¬ºA. 

©Ò¿×ªºÃþ¤ñ¿é¤J¹ê»Ú¬O¶q´ú¨ìªºªý§Ü­È. ¹CÀ¸°ð¦³¥|­Ó³æÀ»¦h¿Ó®¶Àú¾¹
(one-shot multivibrator) (¤@­Ó 558 ´¹¤ù) ³s±µ¨ì¥|­ÓÃþ¤ñ¿é¤J¸}¦ì. 
¨C­ÓÃþ¤ñ¿é¤J¸}¦ì»P¦h¿Ó®¶Àú¾¹ªº¿é¥X¤§¶¡³s±µµÛ¤@­Ó 2.2 Kohm ªº¹qªý, 
¦Ó¥B¦h¿Ó®¶Àú¾¹ªº¿é¥X»P¦a¤§¶¡³s±µµÛ¤@­Ó 0.01 uF ªº®É§Ç¹q®e
(timing capacitor).  ¤@­Ó¹ê»Úªº¾ÞÁa±ì¨ä¨C­Ó®y¼Ð (X ©M Y) ¤W·|¦³¤@­Ó¥iÅÜ¹qªý, 
³s±µ¦b +5 V »P¨C­Ó¬Û¹ïªºÃþ¤ñ¿é¤J¸}¦ì¤§¶¡ (¸}¦ì AX ©Î AY ¬Oµ¹¾ÞÁa±ì A ¥Îªº, 
¦Ó¸}¦ì BX ©Î BY ¬Oµ¹¾ÞÁa±ì B¥Îªº).

¾Þ§@ªº®É­Ô, ¦h¿Ó®¶Àú¾¹±N¨ä¿é¥X³]©w¬°°ª¦ì·Ç (5 V) ¨Ã¥Bµ¥¨ì®É§Ç¹q®e¤Wªº¹qÀ£¹F¨ì
3.3 V ¤§«á±N¬Û¹ïªº¿é¥X³]©w¬°§C¦ì·Ç. ¦]¦¹¾ÞÁa±ì¤¤¦h¿Ó®¶Àú¾¹¿é¥Xªº°ª¦ì·Ç®É¶¡©P´Á
»P¥iÅÜ¹qªýªº¹qªý­È¦¨¥¿¤ñ (¤]´N¬O, ¾ÞÁa±ì¦b¬Û¹ï®y¼Ðªº¦ì¸m), ¦p¤U©Ò¥Ü:
\begin{quotation}
R = (t - 24.2) / 0.011,
\end{quotation}

¨ä¤¤ R ¬O¥iÅÜ¹qªýªºªý§Ü­È (ohms) ¦Ó t ¬O°ª¦ì·Ç®É¶¡©P´Áªºªø«× (¬í).

¦]¦¹­nÅª¥XÃþ¤ñ¿é¤J¸}¦ìªº¼Æ­È, ­º¥ý§A±o±Ò°Ê¦h¿Ó®¶Àú¾¹ (¥H°ð¼g¤Jªº¤è¦¡; ½Ð¬Ý¤U­±),
µM«á¬d¸ß¥|­Ó®y¼Ðªº«H¸¹ª¬ºA(¥H«ùÄòªº°ðÅª¥X¤è¦¡)¤@ª½¨ì«H¸¹ª¬ºA¥Ñ°ª¦ì·ÇÅÜ¦¨§C¦ì·Ç,
­pºâ¨ä°ª¦ì·Ç®É¶¡©P´Áªºªø«×. ³o­Ó«ùÄò¬d¸ßªº°Ê§@ªá¶O¬Û·í¦hªº CPU ®É¶¡, 
¦Ó¥B¦b¤@­Ó«D§Y®Éªº¦h¤uÀô¹Ò¹³¬O (¤@¯ëªº¨Ï¥ÎªÌ¼Ò¦¡ (user-mode) ) Linux, 
©Ò±oªºµ²ªG¤£¬O«D±`·Ç½T¦]¬°§AµLªk¥H©T©wªº®É¶¡¨Ó¬d¸ß«H¸¹ªºª¬ºA 
(°£«D§A¨Ï¥Î®Ö¤ß¼h¦¸ªºÅX°Êµ{¦¡¦Ó¥B§A±o¦b§A¬d¸ßªº®É­Ô§í¨î±¼¤¤Â_ªº²£¥Í,
¦ý¬O³o¼Ë°µ·|®ö¶O§ó¦hªº CPU ®É¶¡). ¦pªG§Aª¾¹D«H¸¹ªºª¬ºA±N·|ªá¶O¤@¬q¤£µuªº®É¶¡
(¼Æ¤Q²@¬í) Å×·|¦¨¬°§C¦ì·Ç, §A¥i¥H¦b¬d¸ß¤§«e©I¥s¨ç¦¡ usleep() ±N CPU 
ªº®É¶¡Åýµ¹¨ä¥L·Q­n°õ¦æªº¦æµ{ (processes).

¹CÀ¸°ð¤¤°ß¤@»Ý­n§A¨Ó¦s¨úªº°ð¦ì§}¬O 0x201 (¨ä¥Lªº°ð¦ì§}¤£¬O°Ê§@¤@¼Ë´N¬O¨S¥Î).
¥ô¦ó¹ï³o­Ó°ð¦ì§}©Ò°µªº¼g¤J°Ê§@ (¤£½×§A¼g¤J¤°»ò) ³£·|±Ò°Ê¦h¿Ó®¶Àú¾¹.
¹ï³o­Ó°ð¦ì§}°µÅª¥X°Ê§@·|¨ú¦^¿é¤J«H¸¹ªºª¬ºA:
\begin{itemize}
\item Bit 0: AX ( (1=°ª¦ì·Ç) ¦h¿Ó®¶Àú¾¹ªº¿é¥Xª¬ºA)
\item Bit 1: AY ( (1=°ª¦ì·Ç) ¦h¿Ó®¶Àú¾¹ªº¿é¥Xª¬ºA)
\item Bit 2: BX ( (1=°ª¦ì·Ç) ¦h¿Ó®¶Àú¾¹ªº¿é¥Xª¬ºA)
\item Bit 3: BY ( (1=°ª¦ì·Ç) ¦h¿Ó®¶Àú¾¹ªº¿é¥Xª¬ºA)
\item Bit 4: BA1 (¼Æ¦ì¿é¤J, 1=°ª¦ì·Ç)
\item Bit 5: BA2 (¼Æ¦ì¿é¤J, 1=°ª¦ì·Ç)
\item Bit 6: BB1 (¼Æ¦ì¿é¤J, 1=°ª¦ì·Ç)
\item Bit 7: BB2 (¼Æ¦ì¿é¤J, 1=°ª¦ì·Ç)
\end{itemize}







\subsection{¦ê¦C°ð (serial port)}

¦pªG§A©Ò»¡ªº¸Ë¸m¬O¤ä´©¤@¨Ç¹³¬O RS-232 ¨ºÃþªºªF¦è, §AÀ³¸Ó¥i¥H¦p§A©ÒÄ@¦a¨Ï¥Î¦ê¦C°ð.
Linux ©Ò´£¨Ñªº¦ê¦C°ðÅX°Êµ{¦¡À³¸Ó¯à°÷À³¥Î¦b¥ô¦ó¦a¤è (§AÀ³¸Ó¤£»Ý­nª½±µ¼¶¼g¦ê¦C°ðµ{¦¡,
©Î¬O®Ö¤ßªºÅX°Êµ{¦¡); ¥L¬Û·í¨ã¦³³q¥Î©Ê, ©Ò¥H¹³¬O¨Ï¥Î«D¼Ð·Çªº bps ³t²v¥H¤Î¨ä¥Lµ¥µ¥À³¸Ó¤£¬O°ÝÃD.
½Ð°Ñ¦Ò {\ttfamily termios(3)} »¡©ú¤å¥ó, ¦ê¦C°ðÅX°Êµ{¦¡­ì©lµ{¦¡½X
({\ttfamily linux/drivers/char/serial.c}), ¥H¤Îºô­¶ \nameurl{http://www.easysw.com/mike/serial/index.html}{} 
¤W¦³§ó¦h¦b Unix §@·~¨t²Î¼¶¼g¦ê¦C°ðµ{¦¡ªº¬ÛÃö¸ê®Æ.




\section{´£¥Ü}

¦pªG§A·Q­n¦³¦nªº I/O «~­È, §A¥i¥H¦b¨Ã¦C°ð¤W¦Û¦æ²Õ¸Ë ADC ¥B/©Î DAC ´¹¤ù 
(´£¥Ü: ¹q·½³¡¤À, ¥i¨Ï¥Î¹CÀ¸°ð¤Wªº©Î±N¥¼¥Î¨ìªººÏºÐ¹q·½³s±µÀY±µ¦Ü ¾÷´ß¤§¥~,
¦pªG§Aªº¸Ë¸m¥\²v®ø¯Ó§C«h¥i¥H®³¨Ã¦C°ð¨Ó¥R·í¹q·½, ¤£µM´N¬O¨Ï¥Î¥~³¡ªº¹q·½¨Ñµ¹),
©Î¬O¶R AD/DA ¥d¤ù (¤j³¡¤À¸ûÂÂ«¬/¸û§C³tªº²£«~¥i¥Ñ I/O °ð±±¨î). ©ÎªÌ¬O Linux 
­µ®Ä¥dÅX°Êµ{¦¡©Ò¤ä´©ªº«K©y­µ®Ä¥d (³t«×ÁÙ¬Û·íªº§Ö) ¤W 1 ©Î 2 ­Ó¤£ºë½T, 
(¥i¯à·|) µLªkÂk¹sªº«H¸¹³q¹D¹ï§A¦Ó¨¥´N°÷¤F.

¨Ï¥Îºë½TªºÃþ¤ñ¸Ë¸m, ¤£·íªº±µ¦a¥i¯à³y¦¨Ãþ¤ñ¿é¥X¤J«H¸¹ªº»~®t. ¦pªG§A¦³³o¤è­±ªº¸gÅç,
§A¥i¯à·|¹Á¸Õ¥H¥ú½¢¦X¾¹¨Ó¹jµ´ (¹q¸£»P§Aªº¸Ë¸m¤§¶¡ {\itshape ©Ò¦³ªº\/} «H¸¹) ¹q¤l¤zÂZ.
¸ÕµÛ±q¹q¸£¤W¨ú±o¥ú½¢¦X¾¹ªº¹q·½ (¦b°ð¤W¥¼¥Î¨ìªº«H¸¹¸}¦ì¥i¥H´£¨Ñ¨¬°÷ªº¹q·½)
¥H¨D¹F¨ì³Ì¨Îªº¹jµ´®ÄªG.

¦pªG§A²{¦b¥¿¦b´M§ä¯à¦b Linux ¤W¨Ï¥Îªº¦L¨ê¹q¸ôªO³]­p³nÅé, ¦³¤@­ÓºÙ¬° Pcb 
§K¶Oªº X11 À³¥Îµ{¦¡À³¸Ó¯à°÷³Ó¥ô, ¥u­n§A¤£­n°µ¤@¨Ç¤Ó½ÆÂøªº¨Æ.
³\¦hªº Linux µo¦æª©¥» (distributions) ³£¤º§t³o­Óµ{¦¡, ¦P®É¥L¤]³Q©ñ¦bºô§} \nameurl{ftp://sunsite.unc.edu/pub/Linux/apps/circuits/}{} ¤W(ÀÉ¦W¬°
{\ttfamily pcb-*}).






\section{°ÝÃD±Æ°£}

\begin{description}
\item[Q1.] \mbox{}

·í§Ú¦s¨ú I/O °ð®Éµ²ªG¸I¨ì segmentation faults ³o­Ó°ÝÃD



\item[A1.] \mbox{}

¤£¬O§Aªºµ{¦¡¨S¦³ root Åv­­, ´N¬O¦]¬°¬Y¨Ç²z¥Ñ¾É­P¨ç¦¡ {\ttfamily ioperm()} 
©I¥s¥¢±Ñ. ÀË¬d¨ç¦¡ {\ttfamily ioperm()} ªº¶Ç¦^­È. ¦P®É, ÀË¬d§A©Ò¦s¨úªº°ð¤]´N¬O§A¥H
¨ç¦¡ {\ttfamily ioperm()} ©Ò±Ò¥Îªº°ð¦ì§} (°Ñ¦Ò Q3).
¦pªG§A¨Ï¥Îªº¬O©µ¿ð®É¶¡ªº¥¨¶°«ü¥O ({\ttfamily inb\_p()}, {\ttfamily outb\_p()}, µ¥µ¥),
°O±o¤]­n©I¥s¨ç¦¡ {\ttfamily ioperm()} ¥H«K¦s¨ú°ð¦ì§} 0x80.



\item[Q2.] \mbox{}

§ÚµLªk§ä¨ì {\ttfamily in*()}, {\ttfamily out*()} µ¥¨ç¦¡³Q©w¸q¦b¦ó³B,
¦P®É gcc ¤]©ê«è°Ñ¦Ò¨ì¥¼©w¸qªº²Å¸¹ (undefined references).



\item[A2.] \mbox{}

§A¦b½sÄ¶µ{¦¡®É¨S¦³¥´¶}³Ì¨Î¤Æ¿ï¶µ ({\ttfamily -O}),
¦]¦¹ gcc ¤£¯à¸ÑªR {\ttfamily asm/io.h} ¤¤ªº¥¨¶°«ü¥O.
©Î¬O§A®Ú¥»´N¨S¦³¨Ï¥Î {\ttfamily \#include $<$asm/io.h$>$}.



\item[Q3.] \mbox{}

{\ttfamily out*()} ¨S¦³°Ê§@, ©Î¬O°Ê§@©Ç©Çªº.



\item[A3.] \mbox{}

ÀË¬d°Ñ¼Æ©Ò©ñ¸mªº¦¸§Ç; ¥LÀ³¸Ó¬O³o¼Ë {\ttfamily outb(value, port)} ,
¦Ó¤£¬O MS-DOS ¤W±`¥Îªº¨º¼Ë {\ttfamily outportb(port, value)} 



\item[Q4.] \mbox{}

§Ú·Q­n±±¨î¤@­Ó¼Ð·Çªº RS-232 ¸Ë¸m/³s±µ¨Ã¦C°ðªº¦Lªí¾÷/¾ÞÁa±ì...



\item[A4.] \mbox{}

§A³Ì¦n¯à°±¤î¦¹¨Æ¦Ó¨Ï¥Î²{¦³ªºÅX°Êµ{¦¡ (¥L­Ì¦s¦b©ó Linux ªº®Ö¤ß¤¤©Î 
X ¦øªA¾¹¤¤©Î¨ä¥Lªº¦a¤è) ¨Ó¹F¦¨§Aªº¥Ø¼Ð. 
³o¨ÇÅX°Êµ{¦¡³q±`¬Û·í¨ã³q¥Î©Ê, ©Ò¥H´Nºâ¬O¦³ÂI¤£¼Ð·Çªº¸Ë¸m, ¥L­Ì³q±`³£¯à¥¿±`¹B§@.
³o¨Ç¼Ð·Ç I/O °ðªº¬ÛÃö¸ê°T½Ð°Ñ¦Ò«e­±»¡¹Lªº¤å¥ó«ü¤Þ.

\end{description}





\section{µ{¦¡½X½d¨Ò}

³oÃä¬O¤@¬q¥Î¨Ó¦s¨ú I/O °ðªºÂ²³æªºµ{¦¡½X½d¨Ò:

\begin{tscreen}
\par
\addvspace{\medskipamount}
\nopagebreak\hrule
\begin{verbatim}
/*
 * example.c: ¤@­Ó¥Î¨Ó¦s¨ú I/O °ðªº«D±`Â²³æªº½d¨Ò
 *
 * ³o­Óµ{¦¡½X¨Ã¨S¦³¤°»ò¥Î³B, ¥L¥u¬O°µ¤F°ðªº¼g¤J, ¼È°±, 
 * ¥H¤Î°ðªºÅª¥X´X­Ó°Ê§@. ½sÄ¶®É½Ð¨Ï¥Î `gcc -O2 -o example example.c',
 * ¨Ã¥H root ªº¨­¥÷°õ¦æ `./example'.
 */

#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>

#define BASEPORT 0x378 /* lp1 */

int main()
{
  /* ¨ú±o°ð¦ì§}ªº¦s¨úÅv­­ */
  if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);}
  
  /* ³]©w°ðªº¿é¥X¸ê®Æ«H¸¹ (D0-7) ¥þ¬°¹s (0) */
  outb(0, BASEPORT);
  
  /* ¥ð®§¤@¤U (100 ms) */
  usleep(100000);
  
  /* ±qª¬ºA°ð (BASE+1) Åª¥X¸ê®Æ¨ÃÅã¥Üµ²ªG */
  printf("status: %d\n", inb(BASEPORT + 1));

  /* §Ú­Ì¤£¦A»Ý­n³o¨Ç°ð¦ì§} */
  if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);}

  exit(0);
}

/* µ²§ô example.c */
\end{verbatim} 
\nopagebreak\hrule 
\addvspace{\medskipamount}
\end{tscreen}







\section{­PÁÂ}

¨ó§U¹L§Úªº¤H¹ê¦b¤Ó¦hµLªk¤@¤@¦C¥X, ¦ýÁÙ¬O­n¸ò¦U¦ì»¡Án¦hÁÂ¤F.
¹ï©Ò¦³¨Ó«H¨ó§U§Úªº¤H¨Ã¨S¦³¤@¤@¦^ÂÐ­P¤W©êºp¤§·N, ¨Ã¦A¦¸ÁÂÁÂ§A­Ìªº¨ó§U.

\end{document}
