\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{ÈçºÎÔÚ Linux ÏÂ×«Ð´³ÌÊ½À´Ê¹ÓÃ 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{±¾ÎÄµÄÄÚÈÝËµÃ÷ÁË Intel x86 ¼Ü¹¹ÏÂÈçºÎÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÖÐ×«Ð´³ÌÊ½À´Ê¹ÓÃÓ²ÌåI/O ²ºÒÔ¼°µÈ´ýÒ»Ð¡¶ÎµÄÊ±¼äÖÜÆÚ.}


\begin{document}
\maketitle
\tableofcontents

\section{½éÉÜ}

±¾ÎÄµÄÄÚÈÝËµÃ÷ÁË Intel x86 ¼Ü¹¹ÏÂÈçºÎÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÖÐ×«Ð´³ÌÊ½À´Ê¹ÓÃÓ²Ìå
I/O ²ºÒÔ¼°µÈ´ýÒ»Ð¡¶ÎµÄÊ±¼äÖÜÆÚ. ÄÚÈÝÔ´×Ôì¶Ò»Æª·Ç³£¶ÌµÄÎÄÕÂ
IO-Port mini-HOWTO Æä×÷ÕßÓë±¾ÎÄÍ¬.

±¾ÎÄ 1995-1997 µÄ°æÈ¨Êôì¶ Riku Saikkonen ËùÓÐ. °æÈ¨ÉùÃ÷Ïê¼ûÍøÒ³
\nameurl{http://sunsite.unc.edu/pub/Linux/docs/HOWTO/COPYRIGHT}{Linux HOWTO copyright}.

Èç¹ûÄú¶Ô±¾ÎÄÓÐÈÎºÎÖ¸½Ì²»ÂÛÊÇ´íÎóÐÞÕý»òÊÇÄÚÈÝ²¹Êö, ¶¼»¶Ó­¼ÄÐÅ¸øÎÒ
({\ttfamily Riku.Saikkonen@hut.fi})...

±¾ÎÄ¶ÔÇ°Ò»´Î·¢ÐÐµÄ°æ±¾ (Mar 30 1997) ×÷ÁËÈçÏÂµÄÐÞÕý:

\begin{itemize}
\item ¶Ôì¶ {\ttfamily inb\_p}/{\ttfamily outb\_p} ºÍ²ºÎ»Ö· 0x80 Ö®¼äµÄ¹ØÏµ×ö³öÁË³ÎÇå.
\item É¾³ýÁË¹Øì¶ {\ttfamily udelay()} º¯Ê½µÄ×ÊÁÏ, ÒòÎª {\ttfamily nanosleep()} º¯Ê½
Ìá¹©ÁË±È½ÏÃ÷È·µÄÊ¹ÓÃ·½·¨.
\item ½«ÄÚÈÝ×ª»»³É Linuxdoc-SGML ¸ñÊ½, ²¢ÇÒÖØÐÂ×÷ÁËÐ©ÐíµÄ±àÅÅ.
\item ¶ÔºÜ¶àµØ·½×÷ÁËÐ©ÐíµÄ²¹ÊöÓëÐÞÕý.
\end{itemize}







\section{ÈçºÎÔÚ C ÓïÑÔÏÂÊ¹ÓÃ I/O ²º}


\subsection{Õý¹æµÄ·½·¨}

ÓÃÀ´´æÈ¡ I/O ²ºµÄ³£Ê½ (Routine) ¶¼·ÅÔÚµµ°¸ {\ttfamily /usr/include/asm/io.h} Àï
(»ò·ÅÔÚºËÐÄÔ­Ê¼Âë³ÌÊ½¼¯µÄ {\ttfamily linux/include/asm-i386/io.h} µµ°¸Àï).
ÕâÐ©³£Ê½ÊÇÒÔµ¥ÐÐ¾Þ¼¯ (inline macros) µÄ·½Ê½Ð´³ÉµÄ, ËùÒÔÊ¹ÓÃÊ±Ö»ÒªÒÔ
{\ttfamily \#include $<$asm/io.h$>$} µÄ·½Ê½ÒýÓÃ¾Í¹»ÁË; ²»ÐèÒª¸½¼ÓÈÎºÎº¯Ê½¹Ý
(libraries).

Òë×¢: ³£Ê½(Routine) Í¨³£ÊÇÖ¸ÏµÍ³ºô½Ð(System Call)Óëº¯Ê½(Function)µÄ×Ü³Æ.

ÒòÎª gcc (ÖÁÉÙ³öÏÖÔÚ 2.7.2.3 ºÍÒÔÇ°µÄ°æ±¾) ÒÔ¼° egcs (ËùÓÐµÄ°æ±¾) µÄÏÞÖÆ,
ÄãÔÚ±àÒëÈÎºÎÊ¹ÓÃµ½ÕâÐ©³£Ê½µÄÔ­Ê¼ÂëÊ± {\itshape ±ØÐë\/} ´ò¿ª×î¼Ñ»¯Ñ¡Ïî
({\ttfamily gcc -O1} »ò½Ï¸ß²ã´ÎµÄ), »òÕßÊÇÔÚ×ö {\ttfamily \#include $<$asm/io.h$>$} 
Õâ¸ö¶¯×÷Ç°Ê¹ÓÃ {\ttfamily \#define extern} ½« extern ¶¨Òå³É¿Õ°×.

ÎªÁË³ý´íµÄÄ¿µÄ, Äã±àÒëÊ±¿ÉÒÔÊ¹ÓÃ {\ttfamily gcc -g -O} (ÖÁÉÙÏÖÔÚµÄ gcc °æ±¾ÊÇÕâÑù),
µ«ÊÇ×î¼Ñ»¯Ö®ááÓÐÊ±¿ÉÄÜ»áÈÃ³ý´íÆ÷ (debugger) µÄÐÐÎª±äµÄÓÐµãÆæ¹Ö. 
Èç¹ûÕâ¸ö×´¿ö¶ÔÄã¶øÑÔÊÇ¸öÀ§ÈÅ, Äã¿ÉÒÔ½«ËùÓÐÊ¹ÓÃµ½ I/O 
²ºµÄ³£Ê½¼¯ÖÐ·ÅÔÚÒ»¸öµµ°¸Àï²¢Ö»ÔÚ±àÒë¸Ãµµ°¸Ê±¡õ´ò¿ª×î¼Ñ»¯Ñ¡Ïî.

ÔÚÄã´æÈ¡ÈÎºÎ I/O ²ºÖ®Ç°, Äã±ØÐëÈÃÄãµÄ³ÌÊ½ÓÐÈç´Ë×öµÄÈ¨ÏÞ. Òª´ï³ÉÕâ¸öÄ¿µÄ
Äã¿ÉÒÔÔÚÄãµÄ³ÌÊ½Ò»¿ªÊ¼µÄµØ·½ (µ«ÊÇÒªÔÚÈÎºÎ I/O ²º´æÈ¡¶¯×÷Ö®Ç°) ºô½Ð 
{\ttfamily ioperm()} Õâ¸öº¯Ê½ (¸Ãº¯Ê½±»Ðû¸æì¶µµ°¸ {\ttfamily unistd.h} , ²¢ÇÒ±»¶¨ÒåÔÚ
ºËÐÄÖÐ). Ê¹ÓÃÓï·¨ÊÇ {\ttfamily ioperm(from, num, turn\_on)},
ÆäÖÐ {\ttfamily from} ÊÇµÚÒ»¸öÔÊÐí´æÈ¡µÄ I/O ²ºÎ»Ö·, {\ttfamily num} ÊÇ½ÓÖøÁ¬Ðø´æÈ¡
I/O ²ºÎ»Ö·µÄÊýÄ¿. ÀýÈç, {\ttfamily ioperm(0x300, 5, 1)} µÄÒâË¼¾ÍÊÇËµÔÊÐí´æÈ¡²º
0x300 µ½ 0x304 (Ò»¹²Îå¸ö²ºÎ»Ö·). ¶ø×îááÒ»¸ö²ÎÊýÊÇÒ»¸ö²¼ÁÖ´úÊýÖµÓÃÀ´Ö¸¶¨ÊÇ·ñ
¸øÓè³ÌÊ½´æÈ¡ I/O ²ºµÄÈ¨ÏÞ (true (1)) »òÊÇ³ýÈ¥´æÈ¡µÄÈ¨ÏÞ (false (0)). Äã
¿ÉÒÔ¶à´Îºô½Ðº¯Ê½ {\ttfamily ioperm()} ÒÔ±ãÊ¹ÓÃ¶à¸ö²»Á¬ÐøµÄ²ºÎ»Ö·. ÖÁì¶Óï·¨µÄÏ¸½ÚÇë
²Î¿¼ {\ttfamily ioperm(2)} µÄÊ¹ÓÃËµÃ÷ÎÄ¼þ.

ÄãµÄ³ÌÊ½±ØÐëÓµÓÐ root µÄÈ¨ÏÞ¡õÄÜºô½Ðº¯Ê½ {\ttfamily ioperm()} ; ËùÒÔÄãÈç¹û²»ÊÇÒÔ
root µÄÉí·ÝÖ´ÐÐ¸Ã³ÌÊ½, ¾ÍÊÇµÃ½«¸Ã³ÌÊ½ setuid ³É root. µ±Äãºô½Ð¹ýº¯Ê½ {\ttfamily ioperm()}
´ò¿ª I/O ²ºµÄ´æÈ¡È¨ÏÞááÄã±ã¿ÉÒÔÄÃµô root µÄÈ¨ÏÞ. ÔÚÄãµÄ³ÌÊ½½áÊøÖ®áá²¢²»ÌØ±ð
ÒªÇóÄãÒÔ {\ttfamily ioperm(..., 0)} Õâ¸ö·½Ê½ÄÃµô I/O ²ºµÄ´æÈ¡È¨ÏÞ; ÒòÎªµ±ÄãµÄ³ÌÊ½
Ö´ÐÐÍê±ÏÖ®ááÕâ¸ö¶¯×÷»á×Ô¶¯Íê³É.

ºô½Ðº¯Ê½ {\ttfamily setuid()} ½«Ä¿Ç°Ö´ÐÐ³ÌÊ½µÄÓÐÐ§Ê¹ÓÃÕßÊ¶±ðÂë (ID) Éè¶¨³É·Ç 
root µÄÊ¹ÓÃÕß²¢²»Ó°ÏìÆäÏÈÇ°ÒÔ {\ttfamily ioperm()} µÄ·½Ê½ËùÈ¡µÃµÄ I/O ²º´æÈ¡È¨ÏÞ,
µ«ÊÇºô½Ðº¯Ê½ {\ttfamily fork()} µÄ·½Ê½È´»áÓÐËùÓ°Ïì (ËäÈ»¸¸ÐÐ³Ì (parent process) 
±£ÓÐ´æÈ¡È¨ÏÞ, µ«ÊÇ×ÓÐÐ³Ì (child process) È´ÎÞ·¨È¡µÃ´æÈ¡È¨ÏÞ). 

º¯Ê½ {\ttfamily ioperm()} Ö»ÄÜÈÃÄãÈ¡µÃ²ºÎ»Ö· 0x000 µ½ 0x3ff µÄ´æÈ¡È¨ÏÞ; ÖÁì¶
½Ï¸ßÎ»Ö·µÄ²º, ÄãµÃÊ¹ÓÃº¯Ê½ {\ttfamily iopl()}  (¸Ãº¯Ê½ÈÃÄãÒ»´Î¿ÉÒÔ´æÈ¡ËùÓÐµÄ²ºÎ»Ö·).
½«È¨ÏÞµÈ¼¶²ÎÊýÖµÉèÎª 3 (ÀýÈç, {\ttfamily iopl(3)}) ÒÔ±ãÄãµÄ³ÌÊ½ÄÜ¹»´æÈ¡ {\itshape ËùÓÐµÄ\/}
I/O ²º (Òò´ËÒªÐ¡ÐÄ --- Èç¹û´æÈ¡µ½´íÎóµÄ²ºÎ»Ö·½«¶ÔÄãµÄµçÄÔÔì³É¸÷ÖÖ²»¿ÉÔ¤ÆÚµÄËðº¦. 
Í¬ÑùµØ, ºô½Ðº¯Ê½ {\ttfamily iopl()} ÄãµÃÓµÓÐ root µÄÈ¨ÏÞ.ÖÁì¶Óï·¨µÄÏ¸½ÚÇë²Î¿¼ 
{\ttfamily iopl(2)} µÄÊ¹ÓÃËµÃ÷ÎÄ¼þ.

½ÓÖø, ÎÒÃÇÀ´Êµ¼ÊµØ´æÈ¡ I/O ²º... Òª´ÓÄ³¸ö²ºÎ»Ö·ÊäÈëÒ»¸ö byte (8 ¸ö bits)
µÄ×ÊÁÏ, ÄãµÃºô½Ðº¯Ê½ {\ttfamily inb(port)} , ¸Ãº¯Ê½»á´«»ØËùÈ¡µÃµÄÒ»¸ö byte µÄ×ÊÁÏ.
ÒªÊä³öÒ»¸ö  byte µÄ×ÊÁÏ, ÄãµÃºô½Ðº¯Ê½ {\ttfamily outb(value, port)}  (Çë¼Ç×¡²ÎÊýµÄ´ÎÐò).
Òª´ÓÄ³¶þ¸ö²ºÎ»Ö· {\ttfamily x} ºÍ {\ttfamily x+1} (¶þ¸ö byte ×é³ÉÒ»¸ö word, ¹ÊÊ¹ÓÃ×éºÏÓïÑÔ
Ö¸Áî {\ttfamily inw}) ÊäÈëÒ»¸ö word (16 ¸ö bits) µÄ×ÊÁÏ, ÄãµÃºô½Ðº¯Ê½ {\ttfamily inw(x)} ;
ÒªÊä³öÒ»¸ö word µÄ×ÊÁÏµ½¶þ¸ö²ºÎ»Ö·, ÄãµÃºô½Ðº¯Ê½ {\ttfamily outw(value, x)} .
Èç¹ûÄã²»È·¶¨Ê¹ÓÃÄÇ¸ö²ºÖ¸Áî (byte »ò word), Äã´ó¸ÅÐëÒª {\ttfamily inb()} Óë {\ttfamily outb()}
Õâ¶þ¸ö²ºÖ¸Áî --- ÒòÎª´ó¶àÊýµÄ×°ÖÃ¶¼ÊÇ²ÉÓÃ byte ´óÐ¡µÄ²º´æÈ¡·½Ê½À´Éè¼ÆµÄ. 
×¢ÒâËùÓÐµÄ²º´æÈ¡Ö¸Áî¶¼ÖÁÉÙÐèÒª´óÔ¼Ò»Î¢ÃëµÄÊ±¼äÀ´Ö´ÐÐ.

Èç¹ûÄãÊ¹ÓÃµÄÊÇ {\ttfamily inb\_p()}, {\ttfamily outb\_p()}, {\ttfamily inw\_p()}, ÒÔ¼° {\ttfamily outw\_p()}
µÈ¾Þ¼¯Ö¸Áî, ÔÚÄã¶Ô²ºÎ»×÷Ö·´æÈ¡¶¯×÷Ö®ááÖ»ÐèºÜ¶ÌµÄ(´óÔ¼Ò»Î¢Ãë)ÑÓ³ÙÊ±¼ä¾Í¿ÉÒÔÍê³É;
ÄãÒ²¿ÉÒÔÈÃÑÓ³ÙÊ±¼ä±ä³É´óÔ¼ËÄÎ¢Ãë·½·¨ÊÇÔÚÊ¹ÓÃ {\ttfamily \#include $<$asm/io.h$>$}
Ö®Ç°Ê¹ÓÃ {\ttfamily \#define REALLY\_SLOW\_IO}. ÕâÐ©¾Þ¼¯Ö¸ÁîÍ¨³£ (³ý·ÇÄãÊ¹ÓÃµÄÊÇ
{\ttfamily \#define SLOW\_IO\_BY\_JUMPING}, Õâ¸ö·½·¨¿ÉÄÜ½Ï²»×¼È·) »áÀûÓÃÊä³ö×ÊÁÏµ½²ºÎ»Ö· 
0x80 ÒÔ±ã´ïµ½ÑÓ³ÙÊ±¼äµÄÄ¿µÄ, ËùÒÔÄãµÃÏÈÒÔº¯Ê½ {\ttfamily ioperm()} È¡µÃ²ºÎ»Ö· 0x80
µÄÊ¹ÓÃÈ¨ÏÞ (Êä³ö×ÊÁÏµ½²ºÎ»Ö· 0x80 ²»Ó¦¸Ã»á¶ÔÏµÍ³µÄÆäËûÆäËû²¿·ÖÔì³ÉÓ°Ïì). ÖÁì¶
ÆäËûÍ¨ÓÃµÄÑÓ³ÙÊ±¼äµÄ·½·¨, Çë¼ÌÐø¶ÁÏÂÈ¥. 

{\ttfamily ioperm(2)}, {\ttfamily iopl(2)} µÈº¯Ê½, ºÍÉÏÃæËùÊö¼°µÄ¾Þ¼¯Ö¸ÁîµÄÊ¹ÓÃËµÃ÷»áÊÕÂ¼ÔÚ
×î½ü³ö°æµÄ Linux Ê¹ÓÃËµÃ÷ÎÄ¼þ¼¯ÖÐ.




\subsection{ÁíÒ»¸öÌæ´úµÄ·½·¨: {\ttfamily /dev/port}}

ÁíÒ»¸ö´æÈ¡ I/O ²ºµÄ·½·¨ÊÇÒÔº¯Ê½ {\ttfamily open()} ¿ªÆôµµ°¸ {\ttfamily /dev/port} 
(Ò»¸ö×ÖÔª×°ÖÃ,Ö÷Òª×°ÖÃ±àºÅÎª 1, ´ÎÒª×°ÖÃ±àºÅÎª 4) ÒÔ±ãÖ´ÐÐ¶ÁÇÒ/»òÐ´µÄ¶¯×÷
(×¢Òâ±ê×¼Êä³öÈë (stdio) º¯Ê½ {\ttfamily f*()} ÓÐÄÚ²¿µÄ»º³å (buffering), ËùÒÔÒª±ÜÃâÊ¹ÓÃ).
½ÓÖøÊ¹ÓÃ {\ttfamily lseek()} º¯Ê½ÒÔ±ãÔÚ¸Ã×ÖÔª×°ÖÃµµ°¸ÖÐÕÒµ½Ä³¸ö byte ×ÊÁÏµÄÕýÈ·Î»ÖÃ
(µµ°¸Î»ÖÃ 0 = ²ºÎ»Ö· 0x00, µµ°¸Î»ÖÃ 1 = ²ºÎ»Ö· 0x01, ÒÔ´ËÀàÍÆ), È»ááÄã¿ÉÒÔÊ¹ÓÃ
{\ttfamily read()} »ò {\ttfamily write()} º¯Ê½¶ÔÄ³¸ö²ºÎ»Ö·×ö¶Á»òÐ´Ò»¸ö byte »ò word ×ÊÁÏµÄ¶¯×÷.

Õâ¸öÌæ´úµÄ·½·¨¾ÍÊÇÔÚÄãµÄ³ÌÊ½ÀïÊ¹ÓÃ read/write º¯Ê½À´´æÈ¡ {\ttfamily /dev/port} 
×ÖÔª×°ÖÃµµ°¸. Õâ¸ö·½·¨µÄÖ´ÐÐËÙ¶È»òÐí±ÈÇ°ÃæËù½²µÄÒ»°ã·½·¨»¹Âý, µ«ÊÇ²»ÐèÒª±àÒëÆ÷
µÄ×î¼Ñ»¯¹¦ÄÜÒ²²»ÐèÒªÊ¹ÓÃº¯Ê½ {\ttfamily ioperm()} . Èç¹ûÄãÔÊÐí·Ç root Ê¹ÓÃÕß»òÈº×é´æÈ¡
{\ttfamily /dev/port} ×ÖÔªÉè×°ÖÃ°¸, ²Ù×÷Ê±¾Í²»ÐèÓµÓÐ root È¨ÏÞ -- µ«ÊÇ¶Ôì¶ÏµÍ³°²È«¶øÑÔ
ÊÇ¸ö·Ç³£Ôã¸âµÄÊÂÇé, ÒòÎªËû¿ÉÄÜÉËº¦µ½ÄãµÄÏµÍ³, »òÐí»áÓÐÈËÒò¶øÈ¡µÄ root µÄÈ¨ÏÞ,
ÀûÓÃ {\ttfamily /dev/port} ×ÖÔª×°ÖÃµµ°¸Ö±½Ó´æÈ¡Ó²µú, ÍøÂ·¿¨, µÈÉè±¸.




\section{Ó²ÌåÖÐ¶Ï (IRQs) Óë DMA ´æÈ¡}

ÄãµÄ³ÌÊ½Èç¹ûÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÏÂÖ´ÐÐ²»¿ÉÒÔÖ±½ÓÊ¹ÓÃÓ²ÌåÖÐ¶Ï (IRQs) »ò DMA. 
Äã±ØÐè×«Ð´Ò»¸öºËÐÄÇý¶¯³ÌÊ½; Ïà¹ØµÄÏ¸½ÚÇë²Î¿¼ÍøÒ³
\nameurl{http://www.redhat.com:8080/HyperNews/get/khg.html}{The Linux Kernel Hacker's Guide} ÒÔ¼°ÄÃºËÐÄ³ÌÊ½Ô­Ê¼ÂëÀ´µ±¡õÀý. 

Ò²¾ÍÊÇËµ, ÄãÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÖÐËùÐ´µÄ³ÌÊ½ÎÞ·¨ÒÖÖÆÓ²ÌåÖÐ¶ÏµÄ²úÉú.




\section{¸ß¾«È·µÄÊ±Ðò}


\subsection{ÑÓ³ÙÊ±¼ä}

Ê×ÏÈ, ÎÒ»áËµ²»±£Ö¤ÄãÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÖÐÖ´ÐÐµÄÐÐ³Ì (process) 
ÄÜ¹»¾«È·µØ¿ØÖÆÊ±ÐòÒòÎª Linux ÊÇ¸ö¶à¹¤µÄ×÷Òµ»·¾³. ÄãÔÚÖ´ÐÐÖÐµÄÐÐ³Ì (process) 
ËæÊ±»áÒòÎª¸÷ÖÖÔ­Òò±»ÔÝÍ£´óÔ¼ 10 ºÁÃëµ½ÊýÃë (ÔÚÏµÍ³¸ººÉ·Ç³£¸ßµÄÊ±ºò). È»¶ø, 
¶Ôì¶´ó¶àÊýÊ¹ÓÃ I/O ²ºµÄÓ¦ÓÃ¶øÑÔ, Õâ¸öÑÓ³ÙÊ±¼äÊµ¼ÊÉÏËã²»ÁËÊ²÷á. ÒªËõ¶ÌÑÓ³ÙÊ±¼ä,
ÄãµÃÊ¹ÓÃº¯Ê½ nice ½«ÄãÔÚÖ´ÐÐÖÐµÄÐÐ³Ì (process ) Éè¶¨³É¸ßÓÅÏÈÈ¨(Çë²Î¿¼ 
{\ttfamily nice(2)} Ê¹ÓÃËµÃ÷ÎÄ¼þ) »òÊ¹ÓÃ¼´Ê±ÅÅ³Ì·¨ (real-time scheduling) (Çë¿´ÏÂÃæ). 

Èç¹ûÄãÏë»ñµÃ±ÈÔÚÒ»°ãÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÖÐÖ´ÐÐµÄÐÐ³Ì (process) 
»¹Òª¾«È·µÄÊ±Ðò, ÓÐÒ»Ð©·½·¨¿ÉÒÔÈÃÄãÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) 
ÖÐ×öµ½ `¼´Ê±' ÅÅ³ÌµÄÖ§Ô®. Linux 2.x °æ±¾µÄºËÐÄÖÐÓÐÈíÌå·½Ê½µÄ¼´Ê±ÅÅ³ÌÖ§Ô®; 
ÏêÏ¸µÄËµÃ÷Çë²Î¿¼ {\ttfamily sched\_setscheduler(2)} Ê¹ÓÃËµÃ÷ÎÄ¼þ. 
ÓÐÒ»¸öÌØÊâµÄºËÐÄÖ§Ô®Ó²ÌåµÄ¼´Ê±ÅÅ³Ì; ÏêÏ¸µÄ×ÊÑ¶Çë²Î¿¼ÍøÒ³ \nameurl{http://luz.cs.nmt.edu/rtlinux/}{} 




\subsubsection{ÐÝÏ¢ÖÐ (Sleeping) : {\ttfamily sleep()} Óë {\ttfamily usleep()}}

ÏÖÔÚ, ÈÃÎÒÃÇ¿ªÊ¼½Ï¼òµ¥µÄÊ±Ðòº¯Ê½ºô½Ð. ÏëÒªÑÓ³ÙÊýÃëµÄÊ±¼ä, ×î¼ÑµÄ·½·¨´ó¸Å
ÊÇÊ¹ÓÃº¯Ê½ {\ttfamily sleep()} . ÏëÒªÑÓ³ÙÖÁÉÙÊýÊ®ºÁÃëµÄÊ±¼ä (10 ms ËÆºõÒÑÊÇ×î¶ÌµÄ
ÑÓ³ÙÊ±¼äÁË), º¯Ê½ {\ttfamily usleep()} Ó¦¸Ã¿ÉÒÔÊ¹ÓÃ. ÕâÐ©º¯Ê½ÊÇÈÃ³ö CPU µÄÊ¹ÓÃÈ¨
¸øÆäËûÏëÒªÖ´ÐÐµÄÐÐ³Ì (processes)  (``×Ô¼ºÐÝÏ¢È¥ÁË''), ËùÒÔÃ»ÓÐÀË·Ñµô CPU 
µÄÊ±¼ä. Ï¸½ÚÇë²Î¿¼ {\ttfamily sleep(3)} Óë {\ttfamily usleep(3)} µÄËµÃ÷ÎÄ¼þ.

Èç¹ûÈÃ³ö CPU µÄÊ¹ÓÃÈ¨Òò¶øÊ¹µÃÊ±¼äÑÓ³ÙÁË´óÔ¼ 50 ºÁÃë (ÕâÈ¡¾öì¶´¦ÀíÆ÷Óë»úÆ÷µÄËÙ¶È, 
ÒÔ¼°ÏµÍ³µÄ¸ººÉ), ¾ÍÀË·Ñµô CPU Ì«¶àµÄÊ±¼ä, ÒòÎª Linux µÄÅÅ³ÌÆ÷ (scheduler) 
(µ¥¾Í x86 ¼Ü¹¹¶øÑÔ) ÔÚ½«¿ØÖÆÈ¨·¢»¹¸øÄãµÄÐÐ³Ì (process) Ö®Ç°Í¨³£ÖÁÉÙÒª»¨·Ñ 
10-30 ºÁÃëµÄÊ±¼ä. Òò´Ë, ¶ÌÊ±¼äµÄÑÓ³Ù, Ê¹ÓÃº¯Ê½ {\ttfamily usleep(3)} 
ËùµÃµ½µÄÑÓ³Ù½á¹ûÍ¨³£»á´óì¶ÄãÔÚ²ÎÊýËùÖ¸¶¨µÄÖµ, ´óÔ¼ÖÁÉÙÓÐ 10 ms. 






\subsubsection{{\ttfamily nanosleep()}}

ÔÚ Linux 2.0.x Ò»ÏµÁÐµÄºËÐÄ·¢ÐÐ°æ±¾ÖÐ, ÓÐÒ»¸öÐÂµÄÏµÍ³ºô½Ð (system call),
{\ttfamily nanosleep()} (Çë²Î¿¼ {\ttfamily nanosleep(2)} µÄËµÃ÷ÎÄ¼þ), ËûÈÃÄãÄÜ¹»
ÐÝÏ¢»òÑÓ³ÙÒ»¸ö¶ÌµÄÊ±¼ä (ÊýÎ¢Ãë»ò¸ü¶à).

Èç¹ûÑÓ³ÙµÄÊ±¼ä $<$= 2 ms, Èô(ÇÒÎ¨Èô)ÄãÖ´ÐÐÖÐµÄÐÐ³Ì (process) Éè¶¨ÁËÈíÌåµÄ¼´Ê±
ÅÅ³Ì (¾ÍÊÇÊ¹ÓÃº¯Ê½ tt/sched\_setscheduler()/), ºô½Ðº¯Ê½ {\ttfamily nanosleep()}  Ê±
²»ÊÇÊ¹ÓÃÒ»¸öÃ¦Âµ»ØÈ¦À´ÑÓ³ÙÊ±¼ä; ¾ÍÊÇ»áÏñº¯Ê½ {\ttfamily usleep()} Ò»ÑùÈÃ³ö CPU
µÄÊ¹ÓÃÈ¨ÐÝÏ¢È¥ÁË.

Õâ¸öÃ¦Âµ»ØÈ¦Ê¹ÓÃº¯Ê½ {\ttfamily udelay()} (Ò»¸öÇý¶¯³ÌÊ½³£»áÓÃµ½µÄºËÐÄÄÚ²¿µÄº¯Ê½)
À´´ï³É, ²¢ÇÒÊ¹ÓÃ BogoMips Öµ (BogoMips ¿ÉÒÔ×¼È·Á¿²âÕâÀàÃ¦Âµ»ØÈ¦µÄËÙ¶È)
À´¼ÆËã»ØÈ¦ÑÓ³ÙµÄÊ±¼ä³¤¶È. ÆäÈçºÎ¶¯×÷µÄÏ¸½ÚÇë²Î¿¼ 
{\ttfamily /usr/include/asm/delay.h}).




\subsubsection{Ê¹ÓÃ I/O ²ºÀ´ÑÓ³ÙÊ±¼ä}

ÁíÒ»¸öÑÓ³ÙÊýÎ¢ÃëµÄ·½·¨ÊÇÊ¹ÓÃ I/O ²º. ¾ÍÊÇ´Ó²ºÎ»Ö· 0x80 ÊäÈë»òÊä³öÈÎºÎ byte 
µÄ×ÊÁÏ (Çë²Î¿¼Ç°Ãæ) µÈ´ýµÄÊ±¼äÓ¦¸Ã¼¸ºõÖ»Òª 1 Î¢ÃëÕâÒª¿´ÄãµÄ´¦ÀíÆ÷µÄÐÍ±ðÓëËÙ¶È.
Èç¹ûÒªÑÓ³ÙÊýÎ¢ÃëµÄÊ±¼äÄã¿ÉÒÔ½«Õâ¸ö¶¯×÷¶à×ö¼¸´Î. ÔÚÈÎºÎ±ê×¼µÄ»úÆ÷ÉÏÊä³ö×ÊÁÏµ½¸Ã
²ºÎ»Ö·Ó¦¸Ã²»»áÓÐ²»Á¼µÄáá¹û¡õ¶Ô (¶øÇÒÓÐÐ©ºËÐÄµÄÉè±¸Çý¶¯³ÌÊ½Ò²ÔÚÊ¹ÓÃËû).
{\ttfamily $\{$in$|$out$\}$[bw]\_p()} µÈº¯Ê½¾ÍÊÇÊ¹ÓÃÕâ¸ö·½·¨À´²úÉúÊ±¼äÑÓ³ÙµÄ
(Çë²Î¿¼µµ°¸ {\ttfamily asm/io.h}).

Êµ¼ÊÉÏ, Ò»¸öÊ¹ÓÃµ½²ºÎ»Ö·¡õÎ§Îª 0-0x3ff µÄ I/O ²ºÖ¸Áî¼¸ºõÖ»Òª 1 Î¢ÃëµÄÊ±¼ä,
ËùÒÔÈç¹ûÄãÒªÈç´Ë×ö, ÀýÈç, Ö±½ÓÊ¹ÓÃ²¢ÁÐ²º, Ö»Òª¼ÓÉÏ¼¸¸ö {\ttfamily inb()} º¯Ê½´Ó¸Ã
²ºÎ»Ö·¡õÎ§¶ÁÈë byte µÄ×ÊÁÏ¼´¿É.




\subsubsection{Ê¹ÓÃ×éºÏÓïÑÔÀ´ÑÓ³ÙÊ±¼ä}

Èç¹ûÄãÖªµÀÖ´ÐÐ³ÌÊ½ËùÔÚ»úÆ÷µÄ´¦ÀíÆ÷ÐÍ±ðÓëÊ±ÖÓËÙ¶È, 
Äã¿ÉÒÔÖ´ÐÐÄ³Ð©×éºÏÓïÑÔÖ¸ÁîÒÔ±ã»ñµÃ½Ï¶ÌµÄÑÓ³ÙÊ±¼ä (µ«ÊÇ¼Ç×¡, 
ÄãÔÚÖ´ÐÐÖÐµÄÐÐ³Ì (process) ËæÊ±»á±»ÔÝÍ£,  ËùÒÔÓÐÊ±ÑÓ³ÙµÄÊ±¼ä»á±ÈÊµ¼Ê³¤). 
ÈçÏÂÃæµÄ±í¸ñËùÊ¾, ÄÚ²¿´¦ÀíÆ÷µÄËÙ¶È¾ö¶¨ÁËËùÒªÊ¹ÓÃµÄÊ±ÖÓÖÜÆÚÊý;
Èç, Ò»¸ö 50 MHz µÄ´¦ÀíÆ÷ (486DX-50 »ò 486DX2-50), Ò»¸öÊ±ÖÓÖÜÆÚÒª»¨·Ñ 1/50000000
Ãë (=200 ÄÎÃë).

\begin{tscreen}
\begin{verbatim}
Ö¸Áî          i386 Ê±ÖÓÖÜÆÚÊý       i486 Ê±ÖÓÖÜÆÚÊý
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}


(¶Ô²»Æð, ÎÒ²»ÖªµÀ Pentiums µÄ×ÊÁÏ, »òÐíÓë i486 ½Ó½ü°É. ÎÒÎÞ·¨ÔÚ i386 
µÄ×ÊÁÏÉÏÕÒµ½Ö»»¨·ÑÒ»¸öÊ±ÖÓÖÜÆÚµÄÖ¸Áî. Èç¹ûÄÜ¹»¾ÍÇëÊ¹ÓÃ»¨·ÑÒ»¸öÊ±ÖÓÖÜÆÚµÄÖ¸Áî,
Òª²»È»¾ÍÊ¹ÓÃ¹ÜÏß¼¼ÊõµÄÐÂÊ½´¦ÀíÆ÷Ò²ÊÇ¿ÉÒÔËõ¶ÌÊ±¼äµÄ.)

ÉÏÃæµÄ±í¸ñÖÐÖ¸Áî {\ttfamily nop} Óë {\ttfamily xchg} Ó¦¸Ã²»»áÓÐ²»Á¼µÄáá¹û. Ö¸Áî×îáá¿ÉÄÜ»á
¸Ä±äÆìºÅÔÝ´æÆ÷µÄÄÚÈÝ, µ«ÊÇÕâÃ»¹ØÏµÒòÎª gcc »á´¦Àí. Ö¸Áî {\ttfamily nop} ÊÇ¸öºÃµÄÑ¡Ôñ.

ÏëÒªÔÚÄãµÄ³ÌÊ½ÖÐÊ¹ÓÃµ½ÕâÐ©Ö¸Áî, ÄãµÃÊ¹ÓÃ {\ttfamily asm({\tt\char`\"}instruction{\tt\char`\"})}.
Ö¸ÁîµÄÓï·¨¾ÍÈçÍ¬ÉÏÃæ±í¸ñµÄÓÃ·¨; Èç¹ûÄãÏëÒªÔÚµ¥Ò»µÄ {\ttfamily asm()} ÐðÊöÖÐÊ¹ÓÃ¶à¸öÖ¸Áî,
¿ÉÒÔÊ¹ÓÃ·ÖºÅ½«ËûÃÇ¸ô¿ª. ÀýÈç,
{\ttfamily asm({\tt\char`\"}nop ; nop ; nop ; nop{\tt\char`\"})} »áÖ´ÐÐËÄ¸ö {\ttfamily nop} Ö¸Áî, 
ÔÚ i486 »ò Pentium ´¦ÀíÆ÷ÖÐ»áÑÓ³ÙËÄ¸öÊ±ÖÓÖÜÆÚ (»òÊÇ i386 »áÑÓ³Ù 12 ¸öÊ±ÖÓÖÜÆÚ).

gcc »á½« {\ttfamily asm()} ·­Òë³Éµ¥ÐÐ×éºÏÓïÑÔ³ÌÊ½Âë, ËùÒÔ²»»áÓÐºô½Ðº¯Ê½µÄ¸ººÉ.

ÔÚ Intel x86 ¼Ü¹¹ÖÐ²»¿ÉÄÜÓÐ±ÈÒ»¸öÊ±ÖÓÖÜÆÚ»¹¶ÌµÄÊ±¼äÑÓ³Ù.




\subsubsection{ÔÚ Pentiums ´¦ÀíÆ÷ÉÏÊ¹ÓÃº¯Ê½ {\ttfamily rdtsc} }

¶Ôì¶ Pentiums ´¦ÀíÆ÷¶øÑÔ, Äã¿ÉÒÔÊ¹ÓÃÏÂÃæµÄ C ÓïÑÔ³ÌÊ½ÂëÀ´È¡µÃ×Ô´ÓÉÏ´ÎÖØÐÂ¿ª»ú
µ½ÏÖÔÚ¾­¹ýÁË¶àÉÙ¸öÊ±ÖÓÖÜÆÚ:

\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}


Äã¿ÉÒÔÑ¯ÎÊ²Î¿¼´ËÖµÒÔ±ãÑÓ³ÙÄãÏëÒªµÄÊ±ÖÓÖÜÆÚÊý.




\subsection{Ê±¼äµÄÁ¿²â}

ÏëÒªÊ±¼ä¾«È·µ½Ò»ÃëÖÓ, Ê¹ÓÃº¯Ê½ {\ttfamily time()} »òÐíÊÇ×î¼òµ¥µÄ·½·¨.
ÏëÒªÊ±¼ä¸ü¾«È·, º¯Ê½ {\ttfamily gettimeofday()} ´óÔ¼¿ÉÒÔ¾«È·µ½Î¢Ãë
(µ«ÊÇÈçÇ°ËùÊö»áÊÜµ½ CPU ÅÅ³ÌµÄÓ°Ïì). ÖÁì¶ Pentiums ´¦ÀíÆ÷,
Ê¹ÓÃÉÏÃæµÄ³ÌÊ½ÂëÆ¬¶Ï¾Í¿ÉÒÔ¾«È·µ½Ò»¸öÊ±ÖÓÖÜÆÚ.

Èç¹ûÄãÒªÄãÖ´ÐÐÖÐµÄÐÐ³Ì (process) ÔÚÒ»¶ÎÊ±¼äµ½ÁËÖ®ááÄÜ¹»±»Í¨Öª (get a signal), 
ÄãµÃÊ¹ÓÃº¯Ê½ {\ttfamily setitimer()} »ò {\ttfamily alarm()} . 
Ï¸½ÚÇë²Î¿¼º¯Ê½µÄÊ¹ÓÃËµÃ÷ÎÄ¼þ.




\section{Ê¹ÓÃÆäËû³ÌÊ½ÓïÑÔ}

ÉÏÃæµÄËµÃ÷¼¯ÖÐÔÚ C ³ÌÊ½ÓïÑÔ. ËûÓ¦¸Ã¿ÉÒÔÖ±½ÓÓ¦ÓÃÔÚ C++ ¼° Objective C Ö®ÉÏ.
ÖÁì¶×éºÏÓïÑÔ²¿·Ö, ËäÈ»Äã±ØÐëÏÈÔÚ C ÓïÑÔÖÐºô½Ðº¯Ê½ {\ttfamily ioperm()} »ò {\ttfamily iopl()} ,
µ«ÊÇÖ®ááÄã¾Í¿ÉÒÔÖ±½ÓÊ¹ÓÃ I/O ²º¶ÁÐ´Ö¸Áî.

ÖÁì¶ÆäËû³ÌÊ½ÓïÑÔ, ³ý·ÇÄã¿ÉÒÔÔÚ¸Ã³ÌÊ½ÓïÑÔÖÐ²åÈëµ¥ÐÐ×éºÏÓïÑÔ»ò 
C ÓïÑÔÖ®³ÌÊ½Âë»òÕßÊ¹ÓÃÉÏÃæËùËµµÄÏµÍ³ºô½Ð, ·ñÔòµ¹²»Èç×«Ð´Ò»¸öÄÚº¬ÓÐ´æÈ¡ 
I/O ²º»òÑÓ³ÙÊ±¼äËù±ØÐèº¯Ê½Ö®¼òµ¥µÄ C Ô­Ê¼³ÌÊ½Âë»òÐí»¹±È½ÏÈÝÒ×, 
±àÒëÖ®ááÔÙÓëÄãµÄ³ÌÊ½Á´½á. 
Òª²»È»¾ÍÊÇÊ¹ÓÃÇ°ÃæËùËµµÄ {\ttfamily /dev/port} ×ÖÔª×°ÖÃµµ°¸.




\section{Ò»Ð©ÓÐÓÃµÄ I/O ²º}

±¾½ÚÌá¹©Ò»Ð©³£ÓÃ I/O ²ºµÄ³ÌÊ½×«Ð´×ÊÑ¶ÕâÐ©¶¼ÊÇ¿ÉÒÔÖ±½ÓÄÃÀ´ÓÃµÄÒ»°ãÄ¿µÄ
TTL (»ò CMOS) Âß¼­Î»×¼µÄ I/O ²º.

Èç¹ûÄãÒª°´ÕÕÆäÔ­Ê¼µÄÉè¼ÆÄ¿µÄÀ´Ê¹ÓÃÕâÐ©»òÆäËû³£ÓÃµÄI/O ²º 
(ÀýÈç, ¿ØÖÆÒ»°ãµÄÓ¡±í»ú»òÊý¾Ý»ú), ÄãÓ¦¸Ã»áÊ¹ÓÃÏÖ³ÉµÄ×°ÖÃÇý¶¯³ÌÊ½ 
(ËûÍ¨³£±»º¬ÔÚºËÐÄÖÐ) ¶ø²»»áÈç±¾ÎÄËùËµµØÈ¥×«Ð´ I/O ²º³ÌÊ½.
±¾½ÚÖ÷ÒªÊÇÌá¹©¸øÄÇÐ©ÏëÒª½« LCD ÏÔÊ¾Æ÷, ²½½øÂí´ï, »òÊÇÆäËûÉÌÒµµç×Ó²úÆ·
Á¬½Óµ½ PC ±ê×¼ I/O ²ºµÄÈË.

Èç¹ûÄãÏëÒª¿ØÖÆ´óÖÚÊÐ³¡Ëù··ÂôµÄ×°ÖÃÏñÊÇÉ¨ÃèÆ÷ (ÒÑ¾­ÔÚÊÐ³¡··ÂôÁËÒ»¶ÎÆÚ¼ä),
È¥ÕÒ¿´¿´ÊÇ·ñÓÐÏÖ³ÉµÄ Linux ×°ÖÃÇý¶¯³ÌÊ½.
ÍøÒ³ \nameurl{http://sunsite.unc.edu/pub/Linux/docs/HOWTO/Hardware-HOWTO}{Hardware-HOWTO} ÊÇ¸öºÃµÄ²Î¿¼Æðµã.

ÖÁì¶ÏëÒªÖªµÀ¸ü¶àÓÐ¹ØÈçºÎÁ¬½Óµç×Ó×°ÖÃµ½µçÄÔ(ÒÔ¼°Ò»°ãµÄµç×ÓÑ§Ô­Àí)µÄÏà¹Ø×ÊÑ¶ÔòÍøÒ³
\nameurl{http://www.hut.fi/Misc/Electronics/}{} ÊÇ¸öºÃµÄ×ÊÁÏÀ´Ô´. 






\subsection{²¢ÁÐ²º (parallel port)}

²¢ÁÐ²ºµÄ»ù±¾²ºÎ»Ö· (ÒÔÏÂ³ÆÖ®Îª ``{\ttfamily BASE}'') Ö®ì¶ {\ttfamily /dev/lp0} 
ÊÇ 0x3bc , Ö®ì¶ {\ttfamily /dev/lp1} ÊÇ 0x378 , Ö®ì¶ {\ttfamily /dev/lp2} ÊÇ 0x278 .
Èç¹ûÄãÖ»ÊÇÏëÒª¿ØÖÆÒ»Ð©ÏñÊÇÒ»°ãÓ¡±í»úµÄ¶¯×÷, ¿ÉÒÔ²Î¿¼ÍøÒ³ \nameurl{http://sunsite.unc.edu/pub/Linux/docs/HOWTO/Printing-HOWTO}{Printing-HOWTO}. 

³ýÁËÏÂÃæ¼´½«ÃèÊöµÄ±ê×¼½öÊä³ö (output-only) Ä£Ê½, ´ó¶àÊýµÄ²¢ÁÐ²º¶¼ÓÐ `À©³äµÄ'
Ë«Ïò (bidirectional) Ä£Ê½. ÖÁì¶½ÏÐÂµÄ ECP/EPP Ä£Ê½ (ÒÔ¼°Ò»°ãµÄ IEEE 1284 ±ê×¼) ²º¿ÚµÄÏà¹Ø×ÊÁÏ,
¿ÉÒÔ²Î¿¼ÍøÒ³ \nameurl{http://www.fapo.com/}{} ÒÔ¼° \nameurl{http://www.senet.com.au/cpeacock/parallel.htm}{}.
ÒòÎªÔÚÊ¹ÓÃÕßÄ£Ê½ (user-mode) ÖÐµÄ³ÌÊ½ÎÞ·¨Ê¹ÓÃ IRQs »ò DMA, ÏëÒªÊ¹ÓÃ ECP/EPP 
Ä£Ê½Äã»òÐíµÃ×«Ð´Ò»¸öºËÐÄµÄ×°ÖÃÇý¶¯³ÌÊ½; ÎÒÏëÓ¦¸ÃÓÐÈËÐ´ÁËÕâÀàµÄ×°ÖÃÇý¶¯³ÌÊ½, 
µ«ÊÇÏêÇéÎÒ²¢²»ÖªµÀ. 

²ºÎ»Ö· {\ttfamily BASE+0} (×ÊÁÏ²º) ÓÃÀ´¿ØÖÆ×ÊÁÏ²ºµÄÐÅºÅÎ»×¼ (D0 µ½ D7 ·Ö±ð´ú±íÖø 
bits 0 µ½ 7, Î»×¼×´Ì¬: 0 = µÍÎ»×¼ (0 V), 1 = ¸ßÎ»×¼ (5 V)). 
Ò»¸öÐ´Èë×ÊÁÏµ½¸Ã²ºµÄ¶¯×÷»á½«×ÊÁÏÐÅºÅÎ»×¼Ë©×¡ (latches) ÔÚ²ºµÄ½ÅÎ» (pins) ÉÏ.
Ò»¸ö½«¸Ã²ºµÄ×ÊÁÏ¶Á³öµÄ¶¯×÷»á½«ÉÏÒ»´ÎÒÔ±ê×¼½öÊä³ö (output-only) 
Ä£Ê½»òÀ©³äµÄÐ´ÈëÄ£Ê½ËùË©×¡µÄ×ÊÁÏÐÅºÅÎ»×¼¶Á»Ø, »òÊÇÒÔÀ©³ä¶Á³öÄ£Ê½ ´ÓÁíÍâÒ»
¸ö×°ÖÃ½«½ÅÎ»ÉÏµÄ×ÊÁÏÐÅºÅÎ»×¼¶Á»Ø.

²ºÎ»Ö· {\ttfamily BASE+1} (×´Ì¬²º) ÊÇ¸ö½ö¶Á (read-only) µÄ²º, »á½«ÏÂÃæµÄÊäÈëÐÅºÅÎ»×¼¶Á»Ø:
\begin{itemize}
\item Bits 0 ºÍ 1 ±£Áô²»ÓÃ.
\item Bit 2 IRQ µÄ×´Ì¬ (²»ÊÇ¸ö½ÅÎ» (pin) , ÎÒ²»ÖªµÀËûµÄ¹¤×÷Ô­Àí)
\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}

(ÎÒ²»È·¶¨¸ßµÍÎ»×¼µÄµçÑ¹×´Ì¬.)

²ºÎ»Ö· {\ttfamily BASE+2} (¿ØÖÆ²º) ÊÇ¸ö½öÐ´ (write-only) µÄ²º 
(Ò»¸ö½«¸Ã²ºµÄ×ÊÁÏ¶Á³öµÄ¶¯×÷½ö»á½«ÉÏÒ»´ÎÐ´ÈëµÄ×ÊÁÏÐÅºÅÎ»×¼¶Á»Ø), ÓÃÀ´¿ØÖÆÏÂÃæµÄ×´Ì¬ÐÅºÅ:
\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 µ±±»Éè¶¨Îª 1 Ê±ÔÊÐí²¢ÁÐ²º²úÉú IRQ ÐÅºÅ 
(·¢ÉúÔÚ ACK ½ÅÎ»µÄÎ»×¼ÓÉµÍ±ä¸ßµÄË²¼ä)  
\item Bit 5 ÓÃÀ´¿ØÖÆÀ©³äÄ£Ê½Ê±²ºµÄÊä³öÈë·½Ïò (0 = Ð´, 1 = ¶Á),
ÕâÊÇ¸ö½öÐ´ (write-only) µÄ²º (Ò»¸ö½«¸Ã²ºµÄ×ÊÁÏ¶Á³öµÄ¶¯×÷¶Ô´Ë bit Ò»µãÓÃ´¦Ò²Ã»ÓÐ).
\item Bits 6 and 7 ±£Áô²»ÓÃ.
\end{itemize}

(Í¬ÑùµØ, ÎÒ²»È·¶¨¸ßµÍÎ»×¼µÄµçÑ¹×´Ì¬.)

²ºµÄ½ÅÎ»ÅÅÁÐ (Pinout) ·½Ê½ (¸Ã²ºÊÇÒ»¸ö 25 Ö»½Å D ×ÖÐÎÍâ¿Ç (D-shell) µÄÄ¸Í·Á¬½ÓÆ÷)
(i=ÊäÈë, o=Êä³ö):
\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 µÄ¹æ¸ñÎÄ¼þÉÏËµ½ÅÎ» 1, 14, 16, ºÍ 17 (¿ØÖÆÐÅºÅµÄÊä³ö) ²ÉÓÃµç¾§ÌåµÄ¿ª¼¯¼«
(open collector) Çý¶¯·½Ê½±ØÐèÊ¹ÓÃ 4.7 ÇªÅ·Ä· (kiloohm) µÄÌáÉýµç×è½ÓÖÁ 
5 V µÄµçÑ¹ (¿ÉÁ÷ÈëµçÁ÷ 20 mA, Á÷³öµçÁ÷ 0.55 mA, ¸ßÎ»×¼µÄÊä³öµçÑ¹¾ÍÊÇ 
5.0 V ¼õÈ¥ÌáÉýµç×èµÄµçÑ¹). Ê£ÏÂÀ´µÄ½ÅÎ»¿ÉÁ÷ÈëµçÁ÷ 24 mA, Á÷³öµçÁ÷ 15 mA, 
¸ßÎ»×¼µÄÊä³öµçÑ¹×îÐ¡ 2.4 V. µÍÎ»×¼µÄÊä³öµçÑ¹¶þÕß¶¼ÊÇ×î´ó 0.5 V.
ÄÇÐ©·Ç IBM ¹æ¸ñµÄ²¢ÁÐ²º»òÐí»áÆ«ÀëÕâ¸ö±ê×¼. ¸ü¶àµÄÏà¹Ø×ÊÁÏÇë²Î¿¼ÍøÒ³
\nameurl{http://www.hut.fi/Misc/Electronics/circuits/lptpower.html}{}.

×îáá, ¸øÄãÒ»¸ö¾¯¸æ: ÁôÐÄ½ÓµØµÄÎÊÌâ. ÎÒÔø¾­ÔÚµçÄÔ»¹ÊÇ¿ª»úµÄ×´¿ö¾ÍÈ¥Á¬½ÓËûÒò¶ø
Åª»µºÃ¼¸¸ö²¢ÁÐ²º. ·¢ÉúÁËÕâÖÖÊÂÇéÄã¿ÉÄÜ»á¾õµÃ»¹ÊÇ²»Òª½«²¢ÁÐ²ºÕû
ºÏµ½Ö÷»ú°åÀïÃæ±È½ÏºÃ. (ÄãÍ¨³£¿ÉÒÔÄÃÒ»Æ¬±ãÒËµÄ±ê×¼ `multi-I/O' ¿¨°²×°µÚ¶þ¸ö
²¢ÁÐ²º; Ö»Òª½«ÆäËû²»ÐèÒªµÄ²ºÍ£ÓÃ, È»áá½«¿¨Æ¬ÉÏ²¢ÁÐ²ºµÄ²ºÎ»Ö·Éè¶¨ÔÚ
¿ÕÖøµÄÎ»Ö·¼´¿É. Äã²»ÐèÔÚÒâ²¢ÁÐ²ºµÄ IRQ Éè¶¨, ÒòÎªÍ¨³£²»»á±»ÓÃµ½.)




\subsection{ÓÎÏ· (²Ù×Ý¡õ) ²º (game port)}

ÓÎÏ·²ºµÄ²ºÎ»Ö·¡õÎ§Îª 0x200-0x207. ÏëÒª¿ØÖÆÒ»°ãµÄ²Ù×Ý¡õ, 
ÓÐÒ»¸öºËÐÄ²ã´ÎµÄ²Ù×Ý¡õÇý¶¯³ÌÊ½, ¿É²Î¿¼ÍøÖ· \nameurl{ftp://sunsite.unc.edu/pub/Linux/kernel/patches/}{},
µµÃû {\ttfamily joystick-*}.

²ºµÄ½ÅÎ»ÅÅÁÐ (Pinout) ·½Ê½ (¸Ã²ºÊÇÒ»¸ö 15 Ö»½Å D ×ÖÐÎÍâ¿Ç (D-shell) µÄÄ¸Í·Á¬½ÓÆ÷):
\begin{itemize}
\item 1,8,9,15: +5 V (µçÔ´)
\item 4,5,12: ½ÓµØ
\item 2,7,10,14: ·Ö±ðÊÇ BA1, BA2, BB1, ºÍ BB2 µÈÊýÎ»ÊäÈë
\item 3,6,11,13: ·Ö±ðÊÇ AX, AY, BX, ºÍ BY µÈ``Àà±È''ÊäÈë
\end{itemize}


+5 V µÄ½ÅÎ»ËÆºõÍ¨³£»á±»Ö±½ÓÁ¬½Óµ½Ö÷»ú°åµÄµçÔ´ÏßÉÏ, ËùÒÔËûÓ¦¸ÃÄÜ¹»Ìá¹©Ïàµ±µÄµçÁ¦,
Õâ»¹Òª¿´ËùÊ¹ÓÃÖ÷»ú°å, µçÔ´¹©¸øÆ÷, ÒÔ¼°ÓÎÏ·²ºµÄÀàÐÍ.

ÊýÎ»ÊäÈëÓÃì¶²Ù×Ý¡õµÄ°´Å¥¿ÉÒÔÈÃÄãÁ¬½Ó¶þ¸ö²Ù×Ý¡õµÄËÄ¸ö°´Å¥ (²Ù×Ý¡õ A ºÍ ²Ù×Ý¡õ B, 
¸÷ÓÐ¶þ¸ö°´Å¥) µ½ÓÎÏ·²ºÒ²¾ÍÊÇÊýÎ»ÊäÈëµÄËÄ¸ö½ÅÎ». ËûÃÇÓ¦¸ÃÊÇÒ»°ã TTL µçÑ¹Î»×¼µÄÊäÈë,
Äã¿ÉÒÔÖ±½Ó´Ó×´Ì¬²º (²Î¿¼ÏÂÃæËµÃ÷) ¶Á³öËûÃÇµÄÎ»×¼×´Ì¬. 
Ò»¸öÊµ¼ÊµÄ²Ù×Ý¡õÔÚ°´Å¥±»Ñ¹ÏÂÊ±»á´«»ØµÍÎ»×¼ (0 V) ×´Ì¬·ñÔò¾ÍÊÇ¸ßÎ»×¼ 
(5V ¾­ÓÉ 1 Kohm µÄµç×èÁ¬½Óµ½µçÔ´½ÅÎ») ×´Ì¬. 

ËùÎ½µÄÀà±ÈÊäÈëÊµ¼ÊÊÇÁ¿²âµ½µÄ×è¿¹Öµ. ÓÎÏ·²ºÓÐËÄ¸öµ¥»÷¶àÐ³Õñ¡õÆ÷
(one-shot multivibrator) (Ò»¸ö 558 ¾§Æ¬) Á¬½Óµ½ËÄ¸öÀà±ÈÊäÈë½ÅÎ». 
Ã¿¸öÀà±ÈÊäÈë½ÅÎ»Óë¶àÐ³Õñ¡õÆ÷µÄÊä³öÖ®¼äÁ¬½ÓÖøÒ»¸ö 2.2 Kohm µÄµç×è, 
¶øÇÒ¶àÐ³Õñ¡õÆ÷µÄÊä³öÓëµØÖ®¼äÁ¬½ÓÖøÒ»¸ö 0.01 uF µÄÊ±ÐòµçÈÝ
(timing capacitor).  Ò»¸öÊµ¼ÊµÄ²Ù×Ý¡õÆäÃ¿¸ö×ù±ê (X ºÍ Y) ÉÏ»áÓÐÒ»¸ö¿É±äµç×è, 
Á¬½ÓÔÚ +5 V ÓëÃ¿¸öÏà¶ÔµÄÀà±ÈÊäÈë½ÅÎ»Ö®¼ä (½ÅÎ» AX »ò AY ÊÇ¸ø²Ù×Ý¡õ A ÓÃµÄ, 
¶ø½ÅÎ» BX »ò BY ÊÇ¸ø²Ù×Ý¡õ BÓÃµÄ).

²Ù×÷µÄÊ±ºò, ¶àÐ³Õñ¡õÆ÷½«ÆäÊä³öÉè¶¨Îª¸ßÎ»×¼ (5 V) ²¢ÇÒµÈµ½Ê±ÐòµçÈÝÉÏµÄµçÑ¹´ïµ½
3.3 V Ö®áá½«Ïà¶ÔµÄÊä³öÉè¶¨ÎªµÍÎ»×¼. Òò´Ë²Ù×Ý¡õÖÐ¶àÐ³Õñ¡õÆ÷Êä³öµÄ¸ßÎ»×¼Ê±¼äÖÜÆÚ
Óë¿É±äµç×èµÄµç×èÖµ³ÉÕý±È (Ò²¾ÍÊÇ, ²Ù×Ý¡õÔÚÏà¶Ô×ù±êµÄÎ»ÖÃ), ÈçÏÂËùÊ¾:
\begin{quotation}
R = (t - 24.2) / 0.011,
\end{quotation}

ÆäÖÐ R ÊÇ¿É±äµç×èµÄ×è¿¹Öµ (ohms) ¶ø t ÊÇ¸ßÎ»×¼Ê±¼äÖÜÆÚµÄ³¤¶È (Ãë).

Òò´ËÒª¶Á³öÀà±ÈÊäÈë½ÅÎ»µÄÊýÖµ, Ê×ÏÈÄãµÃÆô¶¯¶àÐ³Õñ¡õÆ÷ (ÒÔ²ºÐ´ÈëµÄ·½Ê½; Çë¿´ÏÂÃæ),
È»áá²éÑ¯ËÄ¸ö×ù±êµÄÐÅºÅ×´Ì¬(ÒÔ³ÖÐøµÄ²º¶Á³ö·½Ê½)Ò»Ö±µ½ÐÅºÅ×´Ì¬ÓÉ¸ßÎ»×¼±ä³ÉµÍÎ»×¼,
¼ÆËãÆä¸ßÎ»×¼Ê±¼äÖÜÆÚµÄ³¤¶È. Õâ¸ö³ÖÐø²éÑ¯µÄ¶¯×÷»¨·ÑÏàµ±¶àµÄ CPU Ê±¼ä, 
¶øÇÒÔÚÒ»¸ö·Ç¼´Ê±µÄ¶à¹¤»·¾³ÏñÊÇ (Ò»°ãµÄÊ¹ÓÃÕßÄ£Ê½ (user-mode) ) Linux, 
ËùµÃµÄ½á¹û²»ÊÇ·Ç³£×¼È·ÒòÎªÄãÎÞ·¨ÒÔ¹Ì¶¨µÄÊ±¼äÀ´²éÑ¯ÐÅºÅµÄ×´Ì¬ 
(³ý·ÇÄãÊ¹ÓÃºËÐÄ²ã´ÎµÄÇý¶¯³ÌÊ½¶øÇÒÄãµÃÔÚÄã²éÑ¯µÄÊ±ºòÒÖÖÆµôÖÐ¶ÏµÄ²úÉú,
µ«ÊÇÕâÑù×ö»áÀË·Ñ¸ü¶àµÄ CPU Ê±¼ä). Èç¹ûÄãÖªµÀÐÅºÅµÄ×´Ì¬½«»á»¨·ÑÒ»¶Î²»¶ÌµÄÊ±¼ä
(ÊýÊ®ºÁÃë) ¡õ»á³ÉÎªµÍÎ»×¼, Äã¿ÉÒÔÔÚ²éÑ¯Ö®Ç°ºô½Ðº¯Ê½ usleep() ½« CPU 
µÄÊ±¼äÈÃ¸øÆäËûÏëÒªÖ´ÐÐµÄÐÐ³Ì (processes).

ÓÎÏ·²ºÖÐÎ¨Ò»ÐèÒªÄãÀ´´æÈ¡µÄ²ºÎ»Ö·ÊÇ 0x201 (ÆäËûµÄ²ºÎ»Ö·²»ÊÇ¶¯×÷Ò»Ñù¾ÍÊÇÃ»ÓÃ).
ÈÎºÎ¶ÔÕâ¸ö²ºÎ»Ö·Ëù×öµÄÐ´Èë¶¯×÷ (²»ÂÛÄãÐ´ÈëÊ²÷á) ¶¼»áÆô¶¯¶àÐ³Õñ¡õÆ÷.
¶ÔÕâ¸ö²ºÎ»Ö·×ö¶Á³ö¶¯×÷»áÈ¡»ØÊäÈëÐÅºÅµÄ×´Ì¬:
\begin{itemize}
\item Bit 0: AX ( (1=¸ßÎ»×¼) ¶àÐ³Õñ¡õÆ÷µÄÊä³ö×´Ì¬)
\item Bit 1: AY ( (1=¸ßÎ»×¼) ¶àÐ³Õñ¡õÆ÷µÄÊä³ö×´Ì¬)
\item Bit 2: BX ( (1=¸ßÎ»×¼) ¶àÐ³Õñ¡õÆ÷µÄÊä³ö×´Ì¬)
\item Bit 3: BY ( (1=¸ßÎ»×¼) ¶àÐ³Õñ¡õÆ÷µÄÊä³ö×´Ì¬)
\item Bit 4: BA1 (ÊýÎ»ÊäÈë, 1=¸ßÎ»×¼)
\item Bit 5: BA2 (ÊýÎ»ÊäÈë, 1=¸ßÎ»×¼)
\item Bit 6: BB1 (ÊýÎ»ÊäÈë, 1=¸ßÎ»×¼)
\item Bit 7: BB2 (ÊýÎ»ÊäÈë, 1=¸ßÎ»×¼)
\end{itemize}







\subsection{´®ÁÐ²º (serial port)}

Èç¹ûÄãËùËµµÄ×°ÖÃÊÇÖ§Ô®Ò»Ð©ÏñÊÇ RS-232 ÄÇÀàµÄ¶«Î÷, ÄãÓ¦¸Ã¿ÉÒÔÈçÄãËùÔ¸µØÊ¹ÓÃ´®ÁÐ²º.
Linux ËùÌá¹©µÄ´®ÁÐ²ºÇý¶¯³ÌÊ½Ó¦¸ÃÄÜ¹»Ó¦ÓÃÔÚÈÎºÎµØ·½ (ÄãÓ¦¸Ã²»ÐèÒªÖ±½Ó×«Ð´´®ÁÐ²º³ÌÊ½,
»òÊÇºËÐÄµÄÇý¶¯³ÌÊ½); ËûÏàµ±¾ßÓÐÍ¨ÓÃÐÔ, ËùÒÔÏñÊÇÊ¹ÓÃ·Ç±ê×¼µÄ bps ËÙÂÊÒÔ¼°ÆäËûµÈµÈÓ¦¸Ã²»ÊÇÎÊÌâ.
Çë²Î¿¼ {\ttfamily termios(3)} ËµÃ÷ÎÄ¼þ, ´®ÁÐ²ºÇý¶¯³ÌÊ½Ô­Ê¼³ÌÊ½Âë
({\ttfamily linux/drivers/char/serial.c}), ÒÔ¼°ÍøÒ³ \nameurl{http://www.easysw.com/mike/serial/index.html}{} 
ÉÏÓÐ¸ü¶àÔÚ Unix ×÷ÒµÏµÍ³×«Ð´´®ÁÐ²º³ÌÊ½µÄÏà¹Ø×ÊÁÏ.




\section{ÌáÊ¾}

Èç¹ûÄãÏëÒªÓÐºÃµÄ I/O Æ·Öµ, Äã¿ÉÒÔÔÚ²¢ÁÐ²ºÉÏ×ÔÐÐ×é×° ADC ÇÒ/»ò DAC ¾§Æ¬ 
(ÌáÊ¾: µçÔ´²¿·Ö, ¿ÉÊ¹ÓÃÓÎÏ·²ºÉÏµÄ»ò½«Î´ÓÃµ½µÄ´ÅµúµçÔ´Á¬½ÓÍ·½ÓÖÁ »ú¿ÇÖ®Íâ,
Èç¹ûÄãµÄ×°ÖÃ¹¦ÂÊÏûºÄµÍÔò¿ÉÒÔÄÃ²¢ÁÐ²ºÀ´³äµ±µçÔ´, ²»È»¾ÍÊÇÊ¹ÓÃÍâ²¿µÄµçÔ´¹©¸ø),
»òÊÇÂò AD/DA ¿¨Æ¬ (´ó²¿·Ö½Ï¾ÉÐÍ/½ÏµÍËÙµÄ²úÆ·¿ÉÓÉ I/O ²º¿ØÖÆ). »òÕßÊÇ Linux 
ÒôÐ§¿¨Çý¶¯³ÌÊ½ËùÖ§Ô®µÄ±ãÒËÒôÐ§¿¨ (ËÙ¶È»¹Ïàµ±µÄ¿ì) ÉÏ 1 »ò 2 ¸ö²»¾«È·, 
(¿ÉÄÜ»á) ÎÞ·¨¹éÁãµÄÐÅºÅÍ¨µÀ¶ÔÄã¶øÑÔ¾Í¹»ÁË.

Ê¹ÓÃ¾«È·µÄÀà±È×°ÖÃ, ²»µ±µÄ½ÓµØ¿ÉÄÜÔì³ÉÀà±ÈÊä³öÈëÐÅºÅµÄÎó²î. Èç¹ûÄãÓÐÕâ·½ÃæµÄ¾­Ñé,
Äã¿ÉÄÜ»á³¢ÊÔÒÔ¹âñîºÏÆ÷À´¸ô¾ø (µçÄÔÓëÄãµÄ×°ÖÃÖ®¼ä {\itshape ËùÓÐµÄ\/} ÐÅºÅ) µç×Ó¸ÉÈÅ.
ÊÔÖø´ÓµçÄÔÉÏÈ¡µÃ¹âñîºÏÆ÷µÄµçÔ´ (ÔÚ²ºÉÏÎ´ÓÃµ½µÄÐÅºÅ½ÅÎ»¿ÉÒÔÌá¹©×ã¹»µÄµçÔ´)
ÒÔÇó´ïµ½×î¼ÑµÄ¸ô¾øÐ§¹û.

Èç¹ûÄãÏÖÔÚÕýÔÚÑ°ÕÒÄÜÔÚ Linux ÉÏÊ¹ÓÃµÄÓ¡Ë¢µçÂ·°åÉè¼ÆÈíÌå, ÓÐÒ»¸ö³ÆÎª Pcb 
Ãâ·ÑµÄ X11 Ó¦ÓÃ³ÌÊ½Ó¦¸ÃÄÜ¹»Ê¤ÈÎ, Ö»ÒªÄã²»Òª×öÒ»Ð©Ì«¸´ÔÓµÄÊÂ.
Ðí¶àµÄ Linux ·¢ÐÐ°æ±¾ (distributions) ¶¼ÄÚº¬Õâ¸ö³ÌÊ½, Í¬Ê±ËûÒ²±»·ÅÔÚÍøÖ· \nameurl{ftp://sunsite.unc.edu/pub/Linux/apps/circuits/}{} ÉÏ(µµÃûÎª
{\ttfamily pcb-*}).






\section{ÎÊÌâÅÅ³ý}

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

µ±ÎÒ´æÈ¡ I/O ²ºÊ±½á¹ûÅöµ½ segmentation faults Õâ¸öÎÊÌâ



\item[A1.] \mbox{}

²»ÊÇÄãµÄ³ÌÊ½Ã»ÓÐ root È¨ÏÞ, ¾ÍÊÇÒòÎªÄ³Ð©ÀíÓÉµ¼ÖÂº¯Ê½ {\ttfamily ioperm()} 
ºô½ÐÊ§°Ü. ¼ì²éº¯Ê½ {\ttfamily ioperm()} µÄ´«»ØÖµ. Í¬Ê±, ¼ì²éÄãËù´æÈ¡µÄ²ºÒ²¾ÍÊÇÄãÒÔ
º¯Ê½ {\ttfamily ioperm()} ËùÆôÓÃµÄ²ºÎ»Ö· (²Î¿¼ Q3).
Èç¹ûÄãÊ¹ÓÃµÄÊÇÑÓ³ÙÊ±¼äµÄ¾Þ¼¯Ö¸Áî ({\ttfamily inb\_p()}, {\ttfamily outb\_p()}, µÈµÈ),
¼ÇµÃÒ²Òªºô½Ðº¯Ê½ {\ttfamily ioperm()} ÒÔ±ã´æÈ¡²ºÎ»Ö· 0x80.



\item[Q2.] \mbox{}

ÎÒÎÞ·¨ÕÒµ½ {\ttfamily in*()}, {\ttfamily out*()} µÈº¯Ê½±»¶¨ÒåÔÚºÎ´¦,
Í¬Ê± gcc Ò²±§Ô¹²Î¿¼µ½Î´¶¨ÒåµÄ·ûºÅ (undefined references).



\item[A2.] \mbox{}

ÄãÔÚ±àÒë³ÌÊ½Ê±Ã»ÓÐ´ò¿ª×î¼Ñ»¯Ñ¡Ïî ({\ttfamily -O}),
Òò´Ë gcc ²»ÄÜ½âÎö {\ttfamily asm/io.h} ÖÐµÄ¾Þ¼¯Ö¸Áî.
»òÊÇÄã¸ù±¾¾ÍÃ»ÓÐÊ¹ÓÃ {\ttfamily \#include $<$asm/io.h$>$}.



\item[Q3.] \mbox{}

{\ttfamily out*()} Ã»ÓÐ¶¯×÷, »òÊÇ¶¯×÷¹Ö¹ÖµÄ.



\item[A3.] \mbox{}

¼ì²é²ÎÊýËù·ÅÖÃµÄ´ÎÐò; ËûÓ¦¸ÃÊÇÕâÑù {\ttfamily outb(value, port)} ,
¶ø²»ÊÇ MS-DOS ÉÏ³£ÓÃµÄÄÇÑù {\ttfamily outportb(port, value)} 



\item[Q4.] \mbox{}

ÎÒÏëÒª¿ØÖÆÒ»¸ö±ê×¼µÄ RS-232 ×°ÖÃ/Á¬½Ó²¢ÁÐ²ºµÄÓ¡±í»ú/²Ù×Ý¡õ...



\item[A4.] \mbox{}

Äã×îºÃÄÜÍ£Ö¹´ËÊÂ¶øÊ¹ÓÃÏÖÓÐµÄÇý¶¯³ÌÊ½ (ËûÃÇ´æÔÚì¶ Linux µÄºËÐÄÖÐ»ò 
X ËÅ·þÆ÷ÖÐ»òÆäËûµÄµØ·½) À´´ï³ÉÄãµÄÄ¿±ê. 
ÕâÐ©Çý¶¯³ÌÊ½Í¨³£Ïàµ±¾ßÍ¨ÓÃÐÔ, ËùÒÔ¾ÍËãÊÇÓÐµã²»±ê×¼µÄ×°ÖÃ, ËûÃÇÍ¨³£¶¼ÄÜÕý³£ÔË×÷.
ÕâÐ©±ê×¼ I/O ²ºµÄÏà¹Ø×ÊÑ¶Çë²Î¿¼Ç°ÃæËµ¹ýµÄÎÄ¼þÖ¸Òý.

\end{description}





\section{³ÌÊ½Âë¡õÀý}

Õâ±ßÊÇÒ»¶ÎÓÃÀ´´æÈ¡ I/O ²ºµÄ¼òµ¥µÄ³ÌÊ½Âë¡õÀý:

\begin{tscreen}
\par
\addvspace{\medskipamount}
\nopagebreak\hrule
\begin{verbatim}
/*
 * example.c: Ò»¸öÓÃÀ´´æÈ¡ I/O ²ºµÄ·Ç³£¼òµ¥µÄ¡õÀý
 *
 * Õâ¸ö³ÌÊ½Âë²¢Ã»ÓÐÊ²÷áÓÃ´¦, ËûÖ»ÊÇ×öÁË²ºµÄÐ´Èë, ÔÝÍ£, 
 * ÒÔ¼°²ºµÄ¶Á³ö¼¸¸ö¶¯×÷. ±àÒëÊ±ÇëÊ¹ÓÃ `gcc -O2 -o example example.c',
 * ²¢ÒÔ root µÄÉí·ÝÖ´ÐÐ `./example'.
 */

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

#define BASEPORT 0x378 /* lp1 */

int main()
{
  /* È¡µÃ²ºÎ»Ö·µÄ´æÈ¡È¨ÏÞ */
  if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);}
  
  /* Éè¶¨²ºµÄÊä³ö×ÊÁÏÐÅºÅ (D0-7) È«ÎªÁã (0) */
  outb(0, BASEPORT);
  
  /* ÐÝÏ¢Ò»ÏÂ (100 ms) */
  usleep(100000);
  
  /* ´Ó×´Ì¬²º (BASE+1) ¶Á³ö×ÊÁÏ²¢ÏÔÊ¾½á¹û */
  printf("status: %d\n", inb(BASEPORT + 1));

  /* ÎÒÃÇ²»ÔÙÐèÒªÕâÐ©²ºÎ»Ö· */
  if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);}

  exit(0);
}

/* ½áÊø example.c */
\end{verbatim} 
\nopagebreak\hrule 
\addvspace{\medskipamount}
\end{tscreen}







\section{ÖÂÐ»}

Ð­Öú¹ýÎÒµÄÈËÊµÔÚÌ«¶àÎÞ·¨Ò»Ò»ÁÐ³ö, µ«»¹ÊÇÒª¸ú¸÷Î»ËµÉù¶àÐ»ÁË.
¶ÔËùÓÐÀ´ÐÅÐ­ÖúÎÒµÄÈË²¢Ã»ÓÐÒ»Ò»»Ø¸²ÖÂÉÏ±§Ç¸Ö®Òâ, ²¢ÔÙ´ÎÐ»Ð»ÄãÃÇµÄÐ­Öú.

\end{document}
