\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{The Linux Serial Programming HOWTO}
\author{by Peter H. Baumann, {\ttfamily \onlynameurl{Peter.Baumann@dlr.de}}\\ 
ÒëÕß: ÔøÔªÓÓ {\ttfamily \onlynameurl{yytseng@ms16.hinet.net}}}
\date{v1.0, 22 Ò»ÔÂ 1998}
\abstract{±¾ÎÄ¼þ½«ÐðÊöÈçºÎÔÚ Linux »·¾³ÏÂ×«Ð´ÐòÁÐ²ºµÄÍ¨Ñ¶³ÌÊ½.}


\begin{document}
\maketitle
\tableofcontents

\section{¼ò½é}

±¾ÎÄÊÇ Linux ÐòÁÐ²º³ÌÊ½×«Ð´µÄ HOWTO. È«Æª¶¼ÔÚÌÖÂÛÈçºÎÔÚ Linux »·¾³ÏÂ,
ÒÔÐòÁÐ²ºÓëÆäËû ×°ÖÃ/µçÄÔ Í¨Ñ¶µÄ³ÌÊ½Ð´·¨. Ëù½âÊÍµÄ¼¼Êõ°üº¬: ±ê×¼µÄ I/O
(Ö»¾ß±¸ ´«ËÍ/½ÓÊÕ ÏßµÄ), ·ÇÍ¬²½ I/O, ¼° µÈ´ýÀ´×Ô¶àÐÅºÅÔ´µÄÊäÈëÑ¶ºÅ µÄÐ´·¨.

±¾ÎÄ²»»áÐðÊöÈçºÎÉè¶¨ÐòÁÐ²º, ÒòÎªÕâÔÚ Greg Hankins µÄ Serial-HOWTO ÒÑ¾­ÓÐËµÃ÷ÁË.

ÎÒ±ØÐèÇ¿µ÷ÎÒ²¢·Ç´ËÁìÓòÖÐµÄ×¨¼Ò, ¶øÊÇÔÚ×¨°¸ÖÐÔøÓöµ½¹ýÕâÀàµÄÍ¨Ñ¶ÎÊÌâ.
ÔÚÕâËùÌáµ½µÄ¡õÀý³ÌÊ½ÊÇÑÜÉú×Ô miniterm µÄ³ÌÊ½Âë. ¿ÉÔÚ LDP ³ÌÊ½Éè¼ÆÊ¦Ö¸ÄÏÈ¡µÃ
({\ttfamily ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide/lpg-0.4.tar.gz}
¼°ÆäËûÓ³ÉäÕ¾)
ÔÚ¡õÀýÄÇ¸öÄ¿Â¼ÏÂ.

ÎÒ¿ªÊ¼Ð´Õâ·ÝÎÄ¼þÊÇÔÚ 1997 Äê ÁùÔÂ, ÏÖÔÚÎÒÒÑ¾­ÒÆ×ªµ½ WinNT ÒÔÂú×ã¿Í»§µÄÐèÇó,
ÒÔÖÂì¶ÎÒÃ»ÄÜÑ§µÃ¸üÉîÈëµÄÖªÊ¶. Èç¹ûÈÎºÎÈËÓÐÊ²÷áÒâ¼û, ÎÒºÜÀÖÒâ°ÑËü°Ú½øÕâ·ÝÎÄ¼þÖÐ
(²Î¿¼ »ØÀ¡ ÄÇÒ»½Ú). Èç¹ûÓÐÈËÄÜ½ÓÊÖÕâ·Ý¹¤×÷²¢¼ÓÒÔ¸Ä½ø, Çë e-mail ¸øÎÒ.

ËùÓÐµÄ¡õÀý¶¼ÔÚ i386 Linux Kernel 2.0.29 ÏÂ²âÊÔ¹ý. 




\subsection{°æÈ¨}

Linux Serial-Programming-HOWTO µÄ°æÈ¨(C) 1997 ÊÇ Peter Baumann ËùÓÐ.
Linux HOWTO ÎÄ¼þ¿ÉÒÔÍêÕû»ò²¿·ÝÒÔÊµ¼Ê»òµç×ÓÐÍÊ½ÖØÖÆ»òÉ¢²¼, Ö»Òª°æÈ¨Ðû¸æÄÜ±£ÁôÔÚËùÓÐÉ¢²¼µÄ¸±±¾ÖÐ. ÉÌÒµÐÔµÄÖØÖÆÉ¢²¼ÊÇÐí¿É²¢±»¹ÄÀøµÄ; ²»¹ý, Èç¹ûÒÔ´ËÐÍÊ½µÄÉ¢²¼ {\itshape Ó¦¸Ã\/} ¸æÖª×÷Õß.

ËùÓÐÓÐ¹ØµÄ·­Òë, ÑÜÉúµÄ¹¤×÷, »òÕûºÏºÏ²¢ÈÎºÎ Linux HOWTO ÎÄ¼þ½Ô±ØÐëÔÚ´Ë°æÈ¨Ðû¸æ¹æ¡õÖ®ÏÂ. Ò²¾ÍÊÇ, Äã²»¿ÉÒÔ×Ô HOWTO ËùÑÜÉúµÄ¹¤×÷ÖÐ, É¢²¼µÄÎÄ¼þÉÏ¸½¼Ó¶îÍâµÄÏÞÖÆÌõ¿î.
³ýÁËÕâÐ©¹æÔòÖ®Íâ½Ô¿ÉÔÚÄ³ÖÖÌõ¼þµÄÊÚÓë; ÇëÁªÂç Linux HOWTO Ð­µ÷Ô±: ÈçÒÔÏÂËù¸øµÄÎ»Ö·.

¼ò¶øÑÔÖ®, ÎÒÃÇÏ£Íû¾¡¿ÉÄÜµÃÍ¸¹ý¸÷ÖÖ¹ÜµÀ´Ù½øÕâ·Ý×ÊÑ¶µÄÁ÷Í¨, ²»¹ý, ÎÒÇ¿ÁÒµÄÏ£Íû½«°æÈ¨Ðû¸æÖÃì¶ HOWTO µÄÎÄ¼þÉÏ, ÈÎºÎ {\itshape Ïë\/} ÖØÐÂÉ¢²¼ HOWTO µÄÈË, ¾ùÏ£ÍûÄúÄÜÖª»áÎÒÃÇÒ»ÏÂ.

Èç¹ûÄãÓÐÎÊÌâ, Çë¾­ÓÉ email Óë Tim Bynum, Linux HOWTO Ð­µ÷Ô±Á¬Âç, {\ttfamily \onlynameurl{linux-howto@sunsite.unc.edu}}.




\subsection{±¾ÎÄ×îÐÂµÄ°æ±¾}

Serial-Programming-HOWTO ×îÐÂµÄ°æ±¾½«·ÅÔÚ\\ 
{\ttfamily \onlynameurl{ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/Serial-Programming-HOWTO}}
¼°ÆäËûÓ³ÉèÕ¾Ì¨. ÓÐÐí¶àµÄ¸ñÊ½, Èç PostScript ¼° DVI
µÄ°æ±¾·ÅÔÚ {\ttfamily other-formats} Ä¿Â¼ÏÂ.
Serial-Programming-HOWTO Ò²·ÅÔÚ {\ttfamily \onlynameurl{http://sunsite.unc.edu/LDP/HOWTO/Serial-Programming-HOWTO.html}}
²¢»áÃ¿¸öÔÂ°ÚÒ»·Ýµ½ {\ttfamily \onlynameurl{comp.os.linux.answers}}.




\subsection{»ØÀ¡}

Çë°ÑÈÎºÎÐÞÕý, ÎÊÌâ, Òâ¼û, ½¨Òé, »òÆäËü¸½¼ÓµÄÌâ²Ä´«ËÍ¸øÎÒ. ÒÔÈÃÎÒ¸Ä½øÕâ·Ý HOWTO!
²¢ÏêÏ¸¸æËßÎÒÄÄ¸ö²¿·ÝÊÇÄú²»ÄÜÁË½â, »ò²»¹»Çå³þµÄ. Äã¿ÉÒÔÓÃ email Á¬ÂçÎÒ
{\ttfamily \onlynameurl{Peter.Baumann@dlr.de}}.
Çë°Ñ Serial-Programming-HOWTO µÄ°æ±¾ºÅÂë¸½ÉÏ, ±¾ÎÄ°æ±¾ºÅÂëÊÇ 0.3.






\section{¿ªÊ¼}




\subsection{Õì´í}

×îºÃµÄÕì´íÄã³ÌÊ½ÂëµÄ·½·¨ÊÇ½¨¹¹ÁíÒ»Ì¨ Linux box, ²¢°ÑÁ½Ì¨µçÄÔÓÃ null-modem ÀÂÏßÁ¬½Ó. ÓÃ miniterm
(¿ÉÔÚ LDP ³ÌÊ½Éè¼ÆÊ¦Ö¸ÄÏÈ¡µÃ
({\ttfamily ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide/lpg-0.4.tar.gz} ÔÚ¡õÀýÄÇ¸öÄ¿Â¼ÏÂ) ÒÔ´«ËÍ×ÖÔªµ½ÄãµÄ Linux box.
Miniterm ºÜÈÝÒ×±àÒë¶øËü»á°ÑËùÓÐÊäÈëµ½¼üÅÌµÄ×ÖÔªÍ¸¹ýÐòÁÐ²º´«ËÍ.
Ö»ÓÐÕâ¸öÐû¸æ¶¨Òå»á±»¼ì²é
{\ttfamily \#define MODEMDEVICE "/dev/ttyS0"}.
Èç¹ûÊÇ COM1 Éè¶¨Îª {\ttfamily ttyS0}, Èç¹ûÊÇ COM2 Éè¶¨Îª {\ttfamily ttyS1} µÈµÈ..
ÏÈÇ°µÄ²âÊÔÊÇ±ØÒªµÄ, {\itshape ËùÓÐµÄ\/} ×ÖÔª¶¼½«ÒÔ raw ·½Ê½ (²»¾­ÈÎºÎ´¦Àí) Ö±½Ó´«ËÍ. ²âÊÔÊÇ·ñÁ¬½ÓÕýÈ·, ÔÚÁ½Ì¨µçÄÔÉÏ¶¼Æô¶¯ miniterm È»ááËæ±ãÔÚ¼üÅÌÉÏÂÒ°´. ÔÚÆäÖÐÒ»Ì¨ÉÏÊäÈëµÄ×ÖÔªÓ¦¸Ã»áÏÔÊ¾ÔÚÁíÒ»Ì¨µçÄÔÉÏ·´Ö®ÒàÍ¬. µ«ÊäÈëµÄ×ÖÔª²»»á»ØÓ¦µ½ÓëÖ®ÏàÁ¬µÄÓ©Ä»ÉÏ.

Òª×ÔÖÆ null-modem µÄµçÀÂ, Äã±ØÐèÒª°Ñ TxD (´«ËÍ) ¼°
RxD (½ÓÊÕ) Á½Ïß¶Ôµ÷. ÏêÏ¸µÄËµÃ÷ÔÚ Serial-HOWTO µÄµÚ 7 ¶Î.

µ±È»Ò²¿ÉÒÔÖ»ÓÃÒ»Ì¨µçÄÔÀ´×÷ÏàÍ¬µÄ²âÊÔ, Ö»ÒªµçÄÔÉÏÓÐÁ½¸öÎ´Ê¹ÓÃµÄÐòÁÐ²º. µ±È»ÄãÒ²¾ÍÒªÖ´ÐÐÁ½¸ö miniterm À´µ±ÐéÄâ¿ØÖÆÌ¨. Èç¹ûÄãÊÇ½åÓÉ°ÎÈ¥»¬ÊóÀ´È¡µÃÁíÒ»¸öÐòÁÐ²º, ¼ÇµÃÒª°Ñ {\ttfamily /dev/mouse} ×°ÖÃÖØÐÂµ¼Ïò, Èç¹ûËü´æÔÚµÄ»°. Èç¹ûÄãÊ¹ÓÃ¶à²ºµÄÐòÁÐ²º¿ØÖÆ¿¨, ÇëÈ·¶¨ËüÒÑÉè¶¨ÕýÈ·. µ±ÎÒÔÚÎÒµÄµçÄÔÉÏ²âÊÔÊ±Ò²Ôø¾­ÒòÎªÉè¶¨´íÎó¶ø³ö¹ýé³. µ±ÎÒÁ¬µ½ÁíÒ»Ì¨µçÄÔ, Í¨Ñ¶²º¿ªÊ¼´«ËÍ×ÖÔª. ¾ÍÒòÎª¸ÕºÃÕâ²»ÊÇÍêÕûµÄ·ÇÍ¬²½Ê½´«Êä, ËùÒÔ¿ÉÔÚÍ¬Ò»Ì¨µçÄÔÉÏÖ´ÐÐÁ½¸ö³ÌÊ½.




\subsection{Á¬½Ó²ºÉè¶¨}

{\ttfamily /dev/ttyS*} ×°ÖÃ»á±»µ±³ÉÁ¬½Óµ½ÄãµÄ Linux box µÄÖÕ¶Ë»ú, ²¢ÇÒÔÚÆô¶¯áá¾ÍÉè¶¨ºÃÁË. Õâ¸ö¹ÛÄîÔÚÄãÐ´ raw ×°ÖÃµÄÍ¨Ñ¶³ÌÊ½Ê±±ØÐè¼Ç×¡. Ò²¾ÍÊÇËµÕâ¸öÁ¬½Ó²º±»Éè¶¨Îª»ØÓ¦ËùÓÐ×ÔÕâ¸ö×°ÖÃËÍ³öµÄ×ÖÔª, ¶øÓÃÔÚ×ÊÁÏ´«ÊäÊ±Í¨³£ÕâÖÖÒª¸Ä±äÕâÖÖ¹¤×÷Ä£Ê½.

ËùÓÐµÄ²ÎÊý¿ÉÒÔÓÉÒ»¸öÐ¡³ÌÊ½¼òµ¥µÄÍê³É. Éè¶¨²ÎÊý±»·ÅÔÚÒ»¸ö½á¹¹ÌåÄÚ {\ttfamily struct termios}, ËûµÄ¶¨ÒåµµÔÚ {\ttfamily $<$asm/termbits.h$>$}:
\begin{tscreen}
\begin{verbatim}
#define NCCS 19
struct termios {
        tcflag_t c_iflag;               /* ÊäÈëÄ£Ê½Æì±ê */
        tcflag_t c_oflag;               /* Êä³öÄ£Ê½Æì±ê */
        tcflag_t c_cflag;               /* ¿ØÖÆÄ£Ê½Æì±ê */
        tcflag_t c_lflag;               /* ÇøÓòÄ£Ê½Æì±ê */
        cc_t c_line;                    /* ÐÐ¿ØÖÆ (line discipline) */
        cc_t c_cc[NCCS];                /* ¿ØÖÆÌØÐÔ */
};
\end{verbatim}
\end{tscreen}


Õâ¸öµµ°¸Ò²°üº¬ËùÓÐµÄÆì±ê¶¨Òå. ÊäÈëÄ£Ê½Æì±êÔÚ
{\ttfamily c\_iflag} ÕÆ¹ÜËùÓÐµÄÊäÈë´¦Àí, Õâ¾ÍÒâÎ½ÖøÓÉ×°ÖÃÉÏ´«À´µÄ×ÖÔªÔÚ»¹Ã»ÓÃ {\ttfamily read} ¹¦ÄÜ¶ÁÈ¡Ç°¿ÉÒÔÏÈ´¦Àí¹ý. Í¬Àí {\ttfamily c\_oflag} ÕÆ¹ÜËùÓÐµÄÊä³ö´¦Àí. {\ttfamily c\_cflag} °üº¬Á¬½Ó²ºµÄÉè¶¨, Èç ±«ÂÊ, Ã¿×ÖÔª¶àÉÙÎ»Ôª, Í£Ö¹Î»Ôª, µÈµÈ.. ÇøÓòÄ£Ê½Æì±ê·ÅÔÚ {\ttfamily c\_lflag} ÓÃÀ´Õì²â×ÖÔªÊÇ·ñ»ØÓ¦, ¶øÑ¶ºÅ»áËÍµ½ÄãµÄ³ÌÊ½, µÈµÈ.. ×îáá
{\ttfamily c\_cc} ÕóÁÐ¶¨ÒåÁËµµ°¸ÖÕÁËµÄ¿ØÖÆ×ÖÔª, Í£Ö¹,
µÈµÈ..  Ô¤ÉèµÄ¿ØÖÆ×ÖÔªÖµ·ÅÔÚ
{\ttfamily $<$asm/termios.h$>$}. ÓÐ¹ØÆì±êµÄÏ¸½Ú°ÚÔÚÊ¹ÓÃÊÖ²á {\ttfamily termios(3)}. {\ttfamily termios} ½á¹¹ÌåÄÚµÄ
{\ttfamily c\_line} ÐÐ¿ØÖÆ (line discipline) ÔªËØ, ²»ÄÜÔÚ POSIX ÏàÈÝµÄÏµÍ³ÏÂÊ¹ÓÃ
ÒëÕß×¢:ÕâÀïËùËµµÄ line discipline ËäÈ»ÎÒ·­³É ÐÐ¿ØÖÆ µ«»¹ÊÇºÜÄÑËµ³öÄÇÊÇÉá. Èç¹ûÏëÖªµÀÇë¿´¿´ kernel :( .






\subsection{ÐòÁÐ×°ÖÃµÄÊäÈë¹ÛÄî}

ÓÐÈý¸öÊäÈëµÄ¹ÛÄîÒªËµÃ÷. °´ÕÕËùÒªÐ´µÄÓ¦ÓÃ³ÌÊ½Ñ¡ÓÃÊÊºÏµÄ¹ÛÄî. ¾¡Á¿±ÜÃâÊ¹ÓÃ»ØÈ¦À´¶ÁÈ¡µ¥Ò»µÄ×ÖÔªÔÙ×é³É×Ö´®. ÎÒÔøÕâÑù×ö¹ý, »áµô×ÖÔª, ÇÒ¶Ô {\ttfamily read} ¶øÑÔ²»»áÏÔÊ¾ÈÎºÎ´íÎó.




\subsubsection{±ê×¼ÊäÈë³ÌÐò}

ÕâÊÇÖÕ¶Ë»úµÄ±ê×¼´¦Àí³ÌÐò, µ«ÓÃÀ´ÓëÆäËû dl ÐÍÊ½µÄÒÔÐÐÎªµ¥Î»µÄÊäÈëÍ¨Ñ¶Ò²ºÜÓÐÓÃ, Ò²¾ÍÊÇ {\ttfamily read} »á´«»ØÒ»ÕûÐÐÍêÕûµÄÊäÈë×ÊÁÏ. ÐÐÔ¤ÉèµÄÖÕÖ¹×ÖÔªÊÇ {\ttfamily NL}
(ASCII {\ttfamily LF}), µµ°¸½áÊø·û, »òÐÐÖÕÖ¹×ÖÔª. Ô¤Éè»·¾³ÏÂ, {\ttfamily CR} (ÊÇ DOS/Windows Ô¤ÉèµÄÐÐÖÕÖ¹·û) ²»»áÖÕÖ¹Ò»ÐÐµÄÐðÊö.

±ê×¼µÄÊäÈë´¦Àí³ÌÐò»¹¿ÉÒÔ´¦Àí Çå³ý, É¾³ý×Ö, ÖØÓ¡×ÖÔª, ¼°×ª»» {\ttfamily CR} Îª {\ttfamily NL} µÈµÈ¹¦ÄÜ..




\subsubsection{·Ç±ê×¼ÊäÈë³ÌÐò}

·Ç±ê×¼ÊäÈë³ÌÐò¿ÉÒÔÓÃÔÚÐèÒªÃ¿´Î¶ÁÈ¡¹Ì¶¨ÊýÁ¿×ÖÔªµÄÇé¿ö, ²¢ÔÊÐíÊ¹ÓÃ×ÖÔªÊäÈëÊ±¼äµÄ¼ÆÊ±Æ÷. ÕâÖÖÄ£Ê½¿ÉÒÔÓÃÔÚ¶ÁÈ¡¹Ì¶¨×ÖÔªÊýÁ¿µÄÓ¦ÓÃ³ÌÊ½, »òÕßËùÁ¬½ÓµÄ×°ÖÃ»áÍ»È»ËÍ³ö´óÁ¿×ÖÔªµÄ×´¿ö.






\subsubsection{·ÇÍ¬²½Ê½ÊäÈë}

ÒÔÉÏËùÐðÊöµÄÁ½ÖÖÄ£Ê½¶¼¿ÉÒÔÓÃÔÚ·ÇÍ¬²½ÓëÍ¬²½µÄ´«ÊäÄ£Ê½. Ô¤ÉèÊÇÔÚÍ¬²½µÄÄ£Ê½ÏÂ¹¤×÷, Ò²¾ÍÊÇÔÚÉÐÎ´¶ÁÈ¡ÍêÖ®Ç°, {\ttfamily read} µÄ×´Ì¬»á±»×è¶Ï. ¶ø·ÇÍ¬²½Ä£Ê½ÏÂ {\ttfamily read} µÄ×´Ì¬»áÖ±½Ó·µ»Ø²¢ËÍ³öÑ¶ºÅµ½Ëù½ÐÓÃµÄ³ÌÊ½Ö±µ½Íê³É¹¤×÷. Õâ¸öÑ¶ºÅ¿ÉÒÔÓÉÑ¶ºÅµÄ´¦Àí³ÌÊ½ handler...À´½ÓÊÕ.




\subsubsection{µÈ´ýÀ´×Ô¶à¸öÑ¶ºÅÀ´Ô´µÄÊäÈë}

Õâ²¢²»ÊÇÒ»¸ö²»Ò»ÑùµÄÊäÈëÄ£Ê½. Èç¹ûÄãÒªÍ¸¹ýÐòÁÐ²ºÁ¬½Ó²¢´¦Àí¶à¸ö×°ÖÃµÄ»°, ËüÊÇÂúÓÐÓÃµÄ. ÔÚÎÒµÄÓ¦ÓÃ³ÌÊ½ÖÐÎÒ±ØÐèÔÚ¼¸ºõÍ¬Ò»Ê±¼äÄÚ, Í¸¹ý TCP/IP socket ¼°ÐòÁÐ²º´¦ÀíÀ´×ÔÆäËûµçÄÔµÄÊäÈëÑ¶ºÅ. ÏÂÃæÕâ¸ö¡õÀý³ÌÊ½½«µÈ´ýÀ´×ÔÁ½¸ö²»Í¬ÊäÈëÔ´µÄÑ¶ºÅ. Èç¹ûÆäÖÐÒ»¸öÐÅºÅÔ´³öÏÖ, Ëû¾Í»á±»´¦Àí, ¶ø³ÌÊ½»á¼ÌÐøµÈ´ýÐÂµÄÊäÈëÑ¶ºÅ.

ÒÔÏÂÕâ¸ö·½·¨¿´ÆðÀ´Ïàµ±¸²ÔÓ, µ«Çë¼Ç×¡ Linux ÊÇÒ»¸ö¶à¹¤µÄ×÷ÒµÏµÍ³. {\ttfamily select} Õâ¸öÏµÍ³ºô½Ð²¢²»»áÔÚµÈ´ýÊäÈëÑ¶ºÅÊ±°Ñ CPU ¸ºÔØ¼ÓÖØ, ¶øÈç¹ûÄãÓÃ»ØÈ¦·½Ê½À´µÈ´ýÊäÈëÑ¶ºÅ½«Ê¹µÃÆäËüÍ¬Ê±Ö´ÐÐµÄÐÐ³Ì±»ÍÏÂý.






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

ËùÓÐµÄ¡õÀýÀ´Ô´×Ô {\ttfamily miniterm.c}. The type ahead ÔÝ´æÆ÷±»ÏÞÖÆÔÚ 255 ¸ö×ÖÔª,  ¾Í¸ú±ê×¼ÊäÈë³ÌÐòµÄ×î´ó×Ö´®³¤¶ÈÏàÍ¬ ({\ttfamily $<$linux/limits.h$>$} »ò {\ttfamily $<$posix1\_lim.h$>$}).

²Î¿¼³ÌÊ½ÂëÖÐµÄ×¢½âËü»á½âÊÍ²»Í¬ÊäÈëÄ£Ê½µÄÊ¹ÓÃ. ÎÒÏ£ÍûÕâÐ©³ÌÊ½Âë¶¼ÄÜ±»ÁË½â. ±ê×¼ÊäÈë³ÌÐòµÄ³ÌÊ½¡õÀýµÄ×¢½âÐ´µÃ×îºÃ, ÆäËüµÄ¡õÀý¶¼Ö»ÔÚ²»Í¬ì¶ÆäËü¡õÀýµÄµØ·½×ö×¢½â.

ÐðÊö²»ÊÇºÜÍêÕû, µ«¿ÉÒÔ¼¤ÀøÄã¶ÔÕâ¡õÀý×öÊµÑé, ÒÔÑÓÉú³öºÏì¶ÄãËùÐèÓ¦ÓÃ³ÌÊ½µÄ×î¼Ñ½â.

±ðÍü¼ÇÒª°ÑÐòÁÐ²ºµÄÈ¨ÏÞÉè¶¨ÕýÈ· (Ò²¾ÍÊÇ: {\ttfamily chmod a+rw /dev/ttyS1})!






\subsection{±ê×¼ÊäÈë³ÌÐò}

\begin{tscreen}
\begin{verbatim}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

/* ±«ÂÊÉè¶¨±»¶¨ÒåÔÚ <asm/termbits.h>, ÕâÔÚ <termios.h> ±»ÒýÈë */
#define BAUDRATE B38400            
/* ¶¨ÒåÕýÈ·µÄÐòÁÐ²º */
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX ÏµÍ³ÏàÈÝ */

#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE; 

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  char buf[255];
/* 
  ¿ªÆôÊý¾Ý»ú×°ÖÃÒÔ¶ÁÈ¡²¢Ð´Èë¶ø²»ÒÔ¿ØÖÆ tty µÄÄ£Ê½
  ÒòÎªÎÒÃÇ²»Ïë³ÌÊ½ÔÚËÍ³ö CTRL-C áá¾Í±»É±µô.
*/
 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }

 tcgetattr(fd,&oldtio); /* ´¢´æÄ¿Ç°µÄÐòÁÐ²ºÉè¶¨ */
 bzero(&newtio, sizeof(newtio)); /* Çå³ý½á¹¹ÌåÒÔ·ÅÈëÐÂµÄÐòÁÐ²ºÉè¶¨Öµ */

/* 
  BAUDRATE: Éè¶¨ bps µÄËÙ¶È. ÄãÒ²¿ÉÒÔÓÃ cfsetispeed ¼° cfsetospeed À´Éè¶¨.
  CRTSCTS : Êä³ö×ÊÁÏµÄÓ²ÌåÁ÷Á¿¿ØÖÆ (Ö»ÄÜÔÚ¾ßÍêÕûÏßÂ·µÄÀÂÏßÏÂ¹¤×÷
            ²Î¿¼ Serial-HOWTO µÚÆß½Ú)
  CS8     : 8n1 (8 Î»Ôª, ²»×öÍ¬Î»Ôª¼ì²é,1 ¸öÖÕÖ¹Î»Ôª)
  CLOCAL  : ±¾µØÁ¬Ïß, ²»¾ßÊý¾Ý»ú¿ØÖÆ¹¦ÄÜ
  CREAD   : ÖÂÄÜ½ÓÊÕ×ÖÔª
*/
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 
/*
  IGNPAR  : ºöÂÔ¾­Í¬Î»Ôª¼ì²éáá, ´íÎóµÄÎ»Ôª×é
  ICRNL   : ±È CR ¶ÔÓ¦³É NL (·ñÔòµ±ÊäÈëÑ¶ºÅÓÐ CR Ê±²»»áÖÕÖ¹ÊäÈë)
            ÔÚ²»È»°Ñ×°ÖÃÉè¶¨³É raw Ä£Ê½(Ã»ÓÐÆäËüµÄÊäÈë´¦Àí)
*/
 newtio.c_iflag = IGNPAR | ICRNL;
 
/*
 Raw Ä£Ê½Êä³ö.
*/
 newtio.c_oflag = 0;
 
/*
  ICANON  : ÖÂÄÜ±ê×¼ÊäÈë, Ê¹ËùÓÐ»ØÓ¦»úÄÜÍ£ÓÃ, ²¢²»ËÍ³öÐÅºÅÒÔ½ÐÓÃ³ÌÊ½
*/
 newtio.c_lflag = ICANON;
 
/* 
  ³õÊ¼»¯ËùÓÐµÄ¿ØÖÆÌØÐÔ
  Ô¤ÉèÖµ¿ÉÒÔÔÚ /usr/include/termios.h ÕÒµ½, ÔÚ×¢½âÖÐÒ²ÓÐ,
  µ«ÎÒÃÇÔÚÕâ²»ÐèÒª¿´ËüÃÇ
*/
 newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
 newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
 newtio.c_cc[VERASE]   = 0;     /* del */
 newtio.c_cc[VKILL]    = 0;     /* @ */
 newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
 newtio.c_cc[VTIME]    = 0;     /* ²»Ê¹ÓÃ·Ö¸î×ÖÔª×éµÄ¼ÆÊ±Æ÷ */
 newtio.c_cc[VMIN]     = 1;     /* ÔÚ¶ÁÈ¡µ½ 1 ¸ö×ÖÔªÇ°ÏÈÍ£Ö¹ */
 newtio.c_cc[VSWTC]    = 0;     /* '\0' */
 newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
 newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
 newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
 newtio.c_cc[VEOL]     = 0;     /* '\0' */
 newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
 newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
 newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
 newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
 newtio.c_cc[VEOL2]    = 0;     /* '\0' */

/* 
  ÏÖÔÚÇå³ýÊý¾Ý»úÏß²¢Æô¶¯ÐòÁÐ²ºµÄÉè¶¨
*/
 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);

/*
  ÖÕ¶Ë»úÉè¶¨Íê³É, ÏÖÔÚ´¦ÀíÊäÈëÑ¶ºÅ
  ÔÚÕâ¸ö¡õÀý, ÔÚÒ»ÐÐµÄ¿ªÊ¼´¦ÊäÈë 'z' »áÍË³ö´Ë³ÌÊ½.
*/
 while (STOP==FALSE) {     /* »ØÈ¦»áÔÚÎÒÃÇ·¢³öÖÕÖ¹µÄÑ¶ºÅááÌø³ö */
 /* ¼´Ê¹ÊäÈë³¬¹ý 255 ¸ö×ÖÔª, ¶ÁÈ¡µÄ³ÌÊ½¶Î»¹ÊÇ»áÒ»Ö±µÈµ½ÐÐÖÕ½á·û³öÏÖ²ÅÍ£Ö¹.
    Èç¹û¶Áµ½µÄ×ÖÔª×éµÍì¶ÕýÈ·´æÔÚµÄ×ÖÔª×é, ÔòËùÊ£µÄ×ÖÔª»áÔÚÏÂÒ»´Î¶ÁÈ¡Ê±È¡µÃ.
    res ÓÃÀ´´æ·ÅÕæÕý¶Áµ½µÄ×ÖÔª×é¸öÊý */
    res = read(fd,buf,255); 
    buf[res]=0;             /* Éè¶¨×Ö´®ÖÕÖ¹×ÖÔª, ËùÒÔÎÒÃÇÄÜÓÃ printf */
    printf(":%s:%d\n", buf, res);
    if (buf[0]=='z') STOP=TRUE;
 }
 /* »Ø´æ¾ÉµÄÐòÁÐ²ºÉè¶¨Öµ */
 tcsetattr(fd,TCSANOW,&oldtio);
}

\end{verbatim}
\end{tscreen}





\subsection{·Ç±ê×¼ÊäÈë³ÌÐò}

ÔÚ·Ç±ê×¼µÄÊäÈë³ÌÐòÄ£Ê½ÏÂ, ÊäÈëµÄ×ÊÁÏ²»»á±»×éºÏ³ÉÒ»ÐÐ¶øÊäÈëááµÄ´¦Àí¹¦ÄÜ (Çå³ý, É±µô, É¾³ý, µÈµÈ.) ¶¼²»ÄÜÊ¹ÓÃ. Õâ¸öÄ£Ê½ÓÐÁ½¸ö¹¦ÄÜ¿ØÖÆ²ÎÊý:
{\ttfamily c\_cc[VTIME]} Éè¶¨×ÖÔªÊäÈëÊ±¼ä¼ÆÊ±Æ÷, ¼° {\ttfamily c\_cc[VMIN]}
Éè¶¨Âú×ã¶ÁÈ¡¹¦ÄÜµÄ×îµÍ×ÖÔª½ÓÊÕ¸öÊý.

Èç¹û MIN $>$ 0 ÇÒ TIME = 0, MIN Éè¶¨ÎªÂú×ã¶ÁÈ¡¹¦ÄÜµÄ×îµÍ×ÖÔª½ÓÊÕ¸öÊý. ÓÉì¶ TIME ÊÇ Áã, ËùÒÔ¼ÆÊ±Æ÷½«²»±»Ê¹ÓÃ.

Èç¹û MIN = 0 ÇÒ TIME $>$ 0, TIME ½«±»µ±×öÓâÊ±Éè¶¨Öµ. Âú×ã¶ÁÈ¡¹¦ÄÜµÄÇé¿öÎª¶ÁÈ¡µ½µ¥Ò»×ÖÔª, »òÕß³¬¹ý TIME Ëù¶¨ÒåµÄÊ±¼ä (t = TIME *0.1 s). Èç¹û³¬¹ý TIME Ëù¶¨ÒåµÄÊ±¼ä, Ôò²»»á´«»ØÈÎºÎ×ÖÔª.

Èç¹û MIN $>$ 0 ÇÒ TIME $>$ 0, TIME ½«±»µ±×öÒ»¸ö·Ö¸î×ÖÔª×éµÄ¼ÆÊ±Æ÷. Âú×ã¶ÁÈ¡¹¦ÄÜµÄÌõ¼þÎª ½ÓÊÕµ½ MIN ¸öÊýµÄ×ÖÔª, »òÁ½¸ö×ÖÔªµÄ¼ä¸ôÊ±¼ä³¬¹ý TIME Ëù¶¨ÒåµÄÖµ. ¼ÆÊ±Æ÷»áÔÚÃ¿¶Áµ½Ò»¸ö×ÖÔªááÖØÐÂ¼ÆÊ±, ÇÒÖ»»áÔÚµÚÒ»¸ö×ÖÔªÊÕµ½áá²Å»áÆô¶¯.

Èç¹û MIN = 0 ÇÒ TIME = 0, ¶ÁÈ¡¹¦ÄÜ¾ÍÂíÉÏ±»Âú×ã. Ä¿Ç°Ëù´æÔÚµÄ×ÖÔª×é¸öÊý, »òÕß ½«»Ø´«µÄ×ÖÔª×é¸öÊý. ¸ù¾Ý Antonino (²Î¿¼ ¹±Ï×) ËùËµ, Äã¿ÉÒÔÓÃ {\ttfamily fcntl(fd, F\_SETFL, FNDELAY);} ÔÚ¶ÁÈ¡Ç°µÃµ½ÏàÍ¬µÄ½á¹û.

½åÓÉÐÞ¸Ä {\ttfamily newtio.c\_cc[VTIME]} ¼° {\ttfamily newtio.c\_cc[VMIN]} ÉÏÊöµÄÄ£Ê½¾Í¿ÉÒÔ²âÊÔÁË.

\begin{tscreen}
\begin{verbatim}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX ÏµÍ³ÏàÈÝ */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE; 

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  char buf[255];

 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }

 tcgetattr(fd,&oldtio); /* ´¢´æÄ¿Ç°µÄÐòÁÐ²ºÉè¶¨ */

 bzero(&newtio, sizeof(newtio));
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 newtio.c_iflag = IGNPAR;
 newtio.c_oflag = 0;

 /* Éè¶¨ÊäÈëÄ£Ê½ (·Ç±ê×¼ÐÍ, ²»»ØÓ¦,...) */
 newtio.c_lflag = 0;
 
 newtio.c_cc[VTIME]    = 0;   /* ²»Ê¹ÓÃ·Ö¸î×ÖÔª×é¼ÆÊ±Æ÷ */
 newtio.c_cc[VMIN]     = 5;   /* ÔÚ¶ÁÈ¡µ½ 5 ¸ö×ÖÔªÇ°ÏÈÍ£Ö¹ */

 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);


 while (STOP==FALSE) {       /* ÊäÈë»ØÈ¦ */
   res = read(fd,buf,255);   /* ÔÚÊäÈë 5 ¸ö×ÖÔªáá¼´·µ»Ø */
   buf[res]=0;               /* ËùÒÔÎÒÃÇÄÜÓÃ printf... */
   printf(":%s:%d\n", buf, res);
   if (buf[0]=='z') STOP=TRUE;
 }
 tcsetattr(fd,TCSANOW,&oldtio);
}
\end{verbatim}
\end{tscreen}





\subsection{·ÇÍ¬²½Ê½ÊäÈë}

\begin{tscreen}
\begin{verbatim}
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX ÏµÍ³ÏàÈÝ */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE; 

void signal_handler_IO (int status);   /* ¶¨ÒåÑ¶ºÅ´¦Àí³ÌÐò */
int wait_flag=TRUE;                    /* Ã»ÊÕµ½Ñ¶ºÅµÄ»°¾Í»áÊÇ TRUE */

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  struct sigaction saio;           /* definition of signal action */
  char buf[255];

  /* ¿ªÆô×°ÖÃÎª non-blocking (¶ÁÈ¡¹¦ÄÜ»áÂíÉÏ½áÊø·µ»Ø) */
  fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
  if (fd <0) {perror(MODEMDEVICE); exit(-1); }

  /* ÔÚÊ¹×°ÖÃ·ÇÍ¬²½»¯Ç°, °²×°Ñ¶ºÅ´¦Àí³ÌÐò */
  saio.sa_handler = signal_handler_IO;
  saio.sa_mask = 0;
  saio.sa_flags = 0;
  saio.sa_restorer = NULL;
  sigaction(SIGIO,&saio,NULL);
  
  /* ÔÊÐíÐÐ³ÌÈ¥½ÓÊÕ SIGIO Ñ¶ºÅ*/
  fcntl(fd, F_SETOWN, getpid());
  /* Ê¹µµ°¸ake the file descriptor ·ÇÍ¬²½ (Ê¹ÓÃÊÖ²áÉÏËµÖ»ÓÐ O_APPEND ¼°
  O_NONBLOCK, ¶ø F_SETFL Ò²¿ÉÒÔÓÃ...) */
  fcntl(fd, F_SETFL, FASYNC);

  tcgetattr(fd,&oldtio); /* ´¢´æÄ¿Ç°µÄÐòÁÐ²ºÉè¶¨Öµ */
  /* Éè¶¨ÐÂµÄÐòÁÐ²ºÎª±ê×¼ÊäÈë³ÌÐò */
  newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
  newtio.c_iflag = IGNPAR | ICRNL;
  newtio.c_oflag = 0;
  newtio.c_lflag = ICANON;
  newtio.c_cc[VMIN]=1;
  newtio.c_cc[VTIME]=0;
  tcflush(fd, TCIFLUSH);
  tcsetattr(fd,TCSANOW,&newtio);
 
  /* µÈ´ýÊäÈëÑ¶ºÅµÄ»ØÈ¦. ºÜ¶àÓÐÓÃµÄÊÂÎÒÃÇ½«ÔÚÕâ×ö */ 
  while (STOP==FALSE) {
    printf(".\n");usleep(100000);
    /* ÔÚÊÕµ½ SIGIO áá, wait_flag = FALSE, ÊäÈëÑ¶ºÅ´æÔÚÔò¿ÉÒÔ±»¶ÁÈ¡ */
    if (wait_flag==FALSE) { 
      res = read(fd,buf,255);
      buf[res]=0;
      printf(":%s:%d\n", buf, res);
      if (res==1) STOP=TRUE; /* Èç¹ûÖ»ÊäÈë CR ÔòÍ£Ö¹»ØÈ¦ */
      wait_flag = TRUE;      /* µÈ´ýÐÂµÄÊäÈëÑ¶ºÅ */
    }
  }
  /* »Ø´æ¾ÉµÄÐòÁÐ²ºÉè¶¨Öµ */
  tcsetattr(fd,TCSANOW,&oldtio);
}

/***************************************************************************
* Ñ¶ºÅ´¦Àí³ÌÐò. Éè¶¨ wait_flag Îª FALSE, ÒÔÊ¹ÉÏÊöµÄ»ØÈ¦ÄÜ½ÓÊÕ×ÖÔª          *
***************************************************************************/

void signal_handler_IO (int status)
{
  printf("received SIGIO signal.\n");
  wait_flag = FALSE;
}
\end{verbatim}
\end{tscreen}





\subsection{µÈ´ýÀ´×Ô¶à¸öÑ¶ºÅÀ´Ô´µÄÊäÈë}

ÕâÒ»¶ÎºÜ¶Ì. ËüÖ»ÄÜ±»ÄÃÀ´µ±³ÉÐ´³ÌÊ½Ê±µÄÌáÊ¾, ¹Ê¡õÀý³ÌÊ½Ò²ºÜ¼ò¶Ì. µ«Õâ¸ö¡õÀý²»Ö»ÄÜÓÃÔÚÐòÁÐ²ºÉÏ, »¹¿ÉÒÔÓÃÔÚ±»µ±³Éµµ°¸À´Ê¹ÓÃµÄ×°ÖÃÉÏ.

select ºô½Ð¼°°éËæËüËùÒý·¢µÄ¾Þ¼¯¹²ÓÃ {\ttfamily fd\_set}. {\ttfamily fd\_set} ÔòÊÇÒ»¸ö
Î»ÔªÕóÁÐ, ¶øÆäÖÐÃ¿Ò»¸öÎ»Ôª´ú±íÒ»¸öÓÐÐ§µÄµµ°¸ÐðÊö½á¹¹. {\ttfamily select} ºô½Ð½ÓÊÜÒ»¸öÓÐÐ§µÄµµ°¸ÐðÊö½á¹¹²¢´«»Ø {\ttfamily fd\_set} Î»ÔªÕóÁÐ, ¶ø¸ÃÎ»ÔªÕóÁÐÖÐÈôÓÐÄ³Ò»¸öÎ»ÔªÎª 1, ¾Í±íÊ¾Ïà¶ÔÓ³µÄµµ°¸ÐðÊö½á¹¹µÄµµ°¸·¢ÉúÁËÊäÈë, Êä³ö»òÓÐÀýÍâÊÂ¼þ. ¶øÕâÐ©¾Þ¼¯Ìá¹©ÁËËùÓÐ´¦Àí {\ttfamily fd\_set} µÄ¹¦ÄÜ. Òà¿É²Î¿¼ÊÖ²á select(2).

\begin{tscreen}
\begin{verbatim}
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

main()
{
   int    fd1, fd2;  /* ÊäÈëÔ´ 1 ¼° 2 */
   fd_set readfs;    /* µµ°¸ÐðÊö½á¹¹Éè¶¨ */
   int    maxfd;     /* ×î´ó¿ÉÓÃµÄµµ°¸ÐðÊö½á¹¹ */
   int    loop=1;    /* »ØÈ¦ÔÚ TRUE Ê±³ÉÁ¢ */ 

   /* open_input_source ¿ªÆôÒ»¸ö×°ÖÃ, ÕýÈ·µÄÉè¶¨ºÃÐòÁÐ²º,
      ²¢»Ø´«»Ø´Ëµµ°¸ÐðÊö½á¹¹Ìå */
   fd1 = open_input_source("/dev/ttyS1");   /* COM2 */
   if (fd1<0) exit(0);
   fd2 = open_input_source("/dev/ttyS2");   /* COM3 */
   if (fd2<0) exit(0);
   maxfd = MAX (fd1, fd2)+1;  /* ²âÊÔ×î´óÎ»ÔªÊäÈë (fd) */

   /* ÊäÈë»ØÈ¦ */
   while (loop) {
     FD_SET(fd1, &readfs);  /* ²âÊÔÊäÈëÔ´ 1 */
     FD_SET(fd2, &readfs);  /* ²âÊÔÊäÈëÔ´ 2 */
     /* block until input becomes available */
     select(maxfd, &readfs, NULL, NULL, NULL);
     if (FD_ISSET(fd1))         /* Èç¹ûÊäÈëÔ´ 1 ÓÐÑ¶ºÅ */
       handle_input_from_source1();
     if (FD_ISSET(fd2))         /* Èç¹ûÊäÈëÔ´ 2 ÓÐÑ¶ºÅ */
       handle_input_from_source2();
   }

}   
\end{verbatim}
\end{tscreen}


Õâ¸ö¡õÀý³ÌÊ½ÔÚµÈ´ýÊäÈëÑ¶ºÅ³öÏÖÇ°, ²»ÄÜÈ·¶¨Ëü»áÍ£¶ÙÏÂÀ´. Èç¹ûÄãÐèÒªÔÚÊäÈëÊ±¼ÓÈëÓâÊ±¹¦ÄÜ, Ö»Ðè°Ñ select ºô½Ð»»³É:
\begin{tscreen}
\begin{verbatim}
int res;
struct timeval Timeout;

/* Éè¶¨ÊäÈë»ØÈ¦µÄÓâÊ±Öµ */
Timeout.tv_usec = 0;  /* ºÁÃë */
Timeout.tv_sec  = 1;  /* Ãë */
res = select(maxfd, &readfs, NULL, NULL, &Timeout);
if (res==0)
/* µµ°¸ÐðÊö½á¹¹ÊýÔÚ input = 0 Ê±, »á·¢ÉúÊäÈëÓâÊ±. */ 
\end{verbatim}
\end{tscreen}


Õâ¸ö³ÌÊ½»áÔÚ 1 ÃëÖÓááÓâÊ±. Èç¹û³¬¹ýÊ±¼ä, select »á´«»Ø 0, µ«ÊÇÓ¦¸ÃÁôÒâ {\ttfamily Timeout} µÄÊ±¼äµÝ¼õÊÇÓÉ {\ttfamily select} ËùµÈ´ýÊäÈëÑ¶ºÅµÄÊ±¼äÎª»ù×¼. Èç¹ûÓâÊ±µÄÖµÊÇ 0, select »áÂíÉÏ½áÊø·µ»Ø.






\section{ÆäËü×ÊÔ´}



\begin{itemize}
\item Linux Serial-HOWTO ÐðÊöÈçºÎÉè¶¨ÐòÁÐ²º¼°ËùÓÐÏà¹ØµÄÓ²Ìå×ÊÑ¶.
\item ÓÉ Michael Sweet ËùÐ´µÄ \nameurl{http://www.easysw.com/~mike/serial}{Serial Programming Guide for POSIX Compliant Operating Systems}. Õâ¸öÁ¬½áÒÑ¾­»Ä·ÏÁËµ«ÎÒÕÒ²»µ½ËüµÄÐÂÎ»Ö·. ÓÐÈËÖªµÀÄÜÔÚÄÄÕÒµ½ËüÂð? ËüÊÇºÜ°ôµÄÎÄ¼þ!
\item {\ttfamily termios(3)} µÄÊ¹ÓÃÊÖ²á. ÐðÊöËùÓÐÓÐ¹Ø {\ttfamily termios} ½á¹¹ÌåµÄÆì±ê.
\end{itemize}





\section{¹±Ï×}

        
¾Í¸ú¼ò½éËùËµµÄÒ»Ñù, ÎÒ²¢·ÇÔÚÕâÁìÓòÓÐËù×¨¾«, µ«ÎÒ×Ô¼ºÓöµ½ÎÊÌâ, ²¢Í¸¹ýËûÈËµÄ°ïÖúÕÒµ½´ð°¸. ¸ÐÐ»À´×Ô European Transonic Windtunnel µÄ Strudthoff ÏÈÉú, Cologne,  Michael Carter ({\ttfamily mcarter@rocke.electro.swri.edu}), ¼° Peter Waltenberg ({\ttfamily p.waltenberg@karaka.chch.cri.nz})



ÓëÎÒÍ¬Ê±×¼±¸Õâ·ÝÎÄ¼þµÄ Antonino Ianella ({\ttfamily antonino@usa.net} Ëù×­Ð´µÄ Serial-Port-Programming Mini HOWTO. Greg Hankins ÒªÇóÎÒ°Ñ Antonino's Mini-HOWTO
Ò»²¢·ÅÈëÕâ·ÝÎÄ¼þ.

        
Õâ·ÝÎÄ¼þµÄ½á¹¹¼° SGML µÄ¸ñÊ½ÊÇÔ´×Ô Greg Hankins µÄ Serial-HOWTO. ¸ÐÐ» Dave Pfaltzgraff ({\ttfamily Dave\_Pfaltzgraff@patapsco.com}),
Sean Lincolne ({\ttfamily slincol@tpgi.com.au}), Michael Wiedmann
({\ttfamily mw@miwie.in-berlin.de}), ¼° Adrey Bonar ({\ttfamily andy@tipas.lt}) ¸÷·½ÃæµÄÐ­Öú.



\end{document}
