📄 终端驱动原理篇 - aaronychen的专栏 - csdnblog.htm
字号:
<div id="News1_pnlMyResume">
<br/><h3>我的简历</h3>
<div id="job_csdn_net_sr"></div><script src="http://job.csdn.net/myresume/aaronychen.aspx"></script>
</div>
<h3 class="listtitle">软件项目交易</h3><ul class = "list"><li class = "listitem"><iframe style="margin:0; padding:0; width: 180px; height: 32px;" src="http://prj.csdn.net/Csdnprj.html" frameborder="0" scrolling="no" ></iframe></li></ul>
<span id="SubscriptionList"><h3 class="listtitle">订阅博客</h3><ul class="list"><li class="listitem"><a href="http://blog.csdn.net/aaronychen/Rss.aspx" ><img border="0" alt="XML聚合" src="/images/xml.gif" /></a> <a href="http://feeds.feedsky.com/csdn.net/aaronychen" target="_blank"><img border="0" alt="FeedSky" src="/images/feedsky.gif" /></a></li><li class="listitem"><a href="http://www.xianguo.com/subscribe.php?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到鲜果" src="/images/rss_xianguo.jpg"/></a></li><li class="listitem"><a href="http://fusion.google.com/add?feedurl=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到Google" src="/images/rss_google.gif"/></a></li><li class="listitem"><a href="http://www.zhuaxia.com/add_channel.php?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到抓虾" src="/images/rss_zhuaxia.gif"/></a></li><li class="listitem"><a href="http://www.bloglines.com/sub/http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到BlogLines" src="/images/rss_bloglines.gif"/></a></li><li class="listitem"><a href="http://add.my.yahoo.com/rss?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到Yahoo" src="/images/rss_yahoo.gif"/></a></li><li class="listitem"><a href="http://rss.gougou.com/find_rss.jsp?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到GouGou" src="/images/rss_gougou.gif"/></a></li><li class="listitem"><a href="http://www.pageflakes.com/subscribe.aspx?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到飞鸽" src="/images/rss_pageflakes.gif"/></a></li><li class="listitem"><a href="http://www.rojo.com/add-subscription?resource=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到Rojo" src="/images/rss_rojo.gif"/></a></li><li class="listitem"><a href="http://www.newsgator.com/ngs/subscriber/subfext.aspx?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到newsgator" src="/images/rss_newsgator.gif"/></a></li><li class="listitem"><a href="http://www.netvibes.com/subscribe.php?url=http://blog.csdn.net/aaronychen/Rss.aspx" target="_blank"><img border="0" alt="订阅到netvibes" src="/images/rss_netvibes.gif"/></a></li></ul></span>
<span id="RecentVisitors"></span>
<h3 class="listtitle">文章</h3>
<ul class="list"><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/365580.aspx">hardware</a><a href="http://blog.csdn.net/aaronychen/category/365580.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/366076.aspx">linux command</a><a href="http://blog.csdn.net/aaronychen/category/366076.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362847.aspx">linux compilation</a><a href="http://blog.csdn.net/aaronychen/category/362847.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362845.aspx">linux driver</a><a href="http://blog.csdn.net/aaronychen/category/362845.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/361627.aspx">linux fs</a><a href="http://blog.csdn.net/aaronychen/category/361627.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362846.aspx">linux kernel</a><a href="http://blog.csdn.net/aaronychen/category/362846.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362848.aspx">linux usage</a><a href="http://blog.csdn.net/aaronychen/category/362848.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362878.aspx">linux那些事儿之U盘</a><a href="http://blog.csdn.net/aaronychen/category/362878.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/363079.aspx">Linux那些事儿之我是Block层</a><a href="http://blog.csdn.net/aaronychen/category/363079.aspx/rss">(RSS)</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/365581.aspx">系统内存全接触</a><a href="http://blog.csdn.net/aaronychen/category/365581.aspx/rss">(RSS)</a></li></ul><h3 class="listtitle">收藏</h3>
<ul class="list"><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362842.aspx">linux编译</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362840.aspx">linux驱动</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362841.aspx">linux使用</a></li><li class="listitem"><a href="http://blog.csdn.net/aaronychen/category/362844.aspx">linux文件系统</a></li></ul><h3 class="listtitle">相册</h3><!--category title-->
<ul class="list"><li class="listitem"><a href="http://blog.csdn.net/aaronychen/Gallery/365578.aspx">I'm aaron</a></li></ul><h3 class="listtitle">存档</h3>
<ul class="list"><li><a href="/aaronychen/archive/2008/02.aspx">2008年02月(18)</a></li><li><a href="/aaronychen/archive/2008/01.aspx">2008年01月(132)</a></li></ul>
<span id="Anthem_RecentComments_ltlComments__"><span id="RecentComments_ltlComments"><h3 class="listtitle">最近评论</h3>
<ul class="list"><li class="listitem">cctv709896635:<a href="http://blog.csdn.net/aaronychen/archive/2008/01/29/2070976.aspx#767560" Title="点击查看《回复:Linux那些事儿之我是U盘(51)光荣属于苹果,属于诺基亚,属于摩托罗拉,属于索尼爱立信》">写的很好!</a></li></ul>
</span></span>
<br />
<br />
</div>
<div id="main">
<span id="viewpost.ascx_PreviousAndNextEntriesUp" class="PreAndNext"><div align="center"><a href="http://blog.csdn.net/aaronychen/archive/2008/01/31/2074140.aspx">上一篇: Linux那些事儿之我是Block层(1)Block子系统的初始化 </a> | <a href="http://blog.csdn.net/aaronychen/archive/2008/01/29/2072185.aspx">下一篇: Linux的I2C驱动架构</a></div></span><br />
<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script><div class="post"> <div class="postTitle"> <script src="http://wz.csdn.net/javascripts/vote.js"></script><a href="http://blog.csdn.net/aaronychen/archive/2008/01/29/2072186.aspx"><img src='/images/zhuan.gif' border='0' width='15' height='13' /> 终端驱动原理篇</a>  <script src="http://blog.csdn.net/count.aspx?ID=2072186&Type=Rank"></script> </div> <div class="postText"> <p align="center" style="margin: 0cm 7.65pt 0.0001pt 8.9pt; text-align: center;" class="MsoNormal"><strong style=""><span style="font-size: 12pt; font-family: 宋体;">第十四章</span></strong><strong style=""><span lang="EN-US" style="font-size: 12pt;"> Linux</span></strong><strong style=""><span style="font-size: 12pt; font-family: 宋体;">终端设备驱动</span></strong><strong style=""><span lang="EN-US" style="font-size: 12pt;"><o:p></o:p></span></strong></p><p align="left" style="margin: 0cm 7.65pt 0.0001pt 8.9pt; text-align: left;" class="MsoNormal"><strong style=""><span style="font-family: 宋体;">本章导读</span><span lang="EN-US"><o:p></o:p></span></strong></p><p align="left" style="margin: 0cm 7.65pt 0.0001pt 8.9pt; text-align: left;" class="MsoNormal"><span style="font-family: 宋体;">在</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">系统中,终端设备非常重要,没有终端设备,系统将无法向用户反馈信息,</span><span lang="EN-US" style="color: red;">Linux</span><span style="font-family: 宋体; color: red;">中包含控制台、串口和伪终端</span><span lang="EN-US" style="color: red;">3</span><span style="font-family: 宋体; color: red;">类终端设备。</span><span lang="EN-US"><br /> 14.1</span><span style="font-family: 宋体;">节阐述了终端设备的概念及分类,</span><span lang="EN-US">14.2</span><span style="font-family: 宋体;">节给出了</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">终端设备驱动的框架结构,重点描述</span><span lang="EN-US">tty_driver</span><span style="font-family: 宋体;">结构体及其成员。</span><span lang="EN-US">14.3~14.5</span><span style="font-family: 宋体;">节在</span><span lang="EN-US">14.2</span><span style="font-family: 宋体;">节的基础上,分别给出了</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">终端设备驱动模块加载</span><span lang="EN-US">/</span><span style="font-family: 宋体;">卸载函数和</span><span lang="EN-US">open()</span><span style="font-family: 宋体;">、</span><span lang="EN-US">close()</span><span style="font-family: 宋体;">函数,数据读写流程及</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">设备线路设置的编程方法。在</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">中,串口驱动完全遵循</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动的框架结构,但是进行了底层操作的再次封装,</span><span lang="EN-US">14.6</span><span style="font-family: 宋体;">节描述了</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">针对串口</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动的这一封装,</span><span lang="EN-US">14.7</span><span style="font-family: 宋体;">节则具体给出了串口</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动的实现方法。</span><span lang="EN-US">14.8</span><span style="font-family: 宋体;">节基于</span><span lang="EN-US">14.6</span><span style="font-family: 宋体;">和</span><span lang="EN-US">14.7</span><span style="font-family: 宋体;">节的讲解给出了串口</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动的设计实例,即</span><span lang="EN-US">S3C2410</span><span style="font-family: 宋体;">集成</span><span lang="EN-US">UART</span><span style="font-family: 宋体;">的驱动。</span></p><p align="left" style="margin: 0cm 7.65pt 0.0001pt 8.9pt; text-align: left;" class="MsoNormal"><span lang="EN-US"><br /> <strong style="">14.1</strong></span><strong style=""><span style="font-family: 宋体;">终端设备</span><span lang="EN-US"><br /> <span style=""> </span></span></strong><span style="font-family: 宋体;">在</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">系统中,终端是一种字符型设备,它有多种类型,通常使用</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">来简称各种类型的终端设备。</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">是</span><span lang="EN-US">Teletype</span><span style="font-family: 宋体;">的缩写,</span><span lang="EN-US">Teletype</span><span style="font-family: 宋体;">是最早出现的一种终端设备,很像电传打字机,是由</span><span lang="EN-US">Teletype</span><span style="font-family: 宋体;">公司生产的。</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">中包含如下几类终端设备:</span><span lang="EN-US"> <br /> <strong style=""><span style="color: red;">1</span></strong></span><strong style=""><span style="font-family: 宋体; color: red;">、串行端口终端(</span><span lang="EN-US" style="color: red;">/dev/ttySn</span></strong><strong style=""><span style="font-family: 宋体; color: red;">)</span><span lang="EN-US" style="color: red;"> <br /> </span></strong><span lang="EN-US" style="color: red;"><span style=""> </span></span><span style="font-family: 宋体;">串行端口终端(</span><span lang="EN-US">Serial Port Terminal</span><span style="font-family: 宋体;">)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。这些串行端口所对应的设备名称是</span><span style="color: red;"> </span><span lang="EN-US" style="color: blue;">/dev/ttyS0</span><span style="font-family: 宋体; color: blue;">(或</span><span lang="EN-US" style="color: blue;">/dev/tts/0</span><span style="font-family: 宋体; color: blue;">)、</span><span lang="EN-US" style="color: blue;">/dev/ttyS1</span><span style="font-family: 宋体; color: blue;">(或</span><span lang="EN-US" style="color: blue;">/dev/tts/1</span><span style="font-family: 宋体; color: blue;">)</span><span style="font-family: 宋体; color: red;">等,设备号分别是</span><span style="font-family: 宋体; color: blue;">(</span><span lang="EN-US" style="color: blue;">4,0</span><span style="font-family: 宋体; color: blue;">)、(</span><span lang="EN-US" style="color: blue;">4,1</span><span style="font-family: 宋体; color: blue;">)</span><span style="font-family: 宋体; color: red;">等。</span><span lang="EN-US" style="color: red;"><br /> <span style=""> </span></span><span style="font-family: 宋体;">在命令行上把标准输出重定向到端口对应的设备文件名上就可以通过该端口发送数据,例如,在命令行提示符下键入:</span><span lang="EN-US" style="color: blue;"> echo test > /dev/ttyS1</span><span style="font-family: 宋体;">会把单词</span><span lang="EN-US">“test”</span><span style="font-family: 宋体;">发送到连接在</span><span lang="EN-US">ttyS1</span><span style="font-family: 宋体;">端口的设备上。</span><span lang="EN-US"> <br /> <strong style=""><span style="color: red;">2.</span></strong></span><strong style=""><span style="font-family: 宋体; color: red;">伪终端(</span><span lang="EN-US" style="color: red;">/dev/pty/</span></strong><strong style=""><span style="font-family: 宋体; color: red;">)</span><span lang="EN-US" style="color: red;"> <br /> <span style=""> </span></span></strong><span style="font-family: 宋体; color: red;">伪终端(</span><span lang="EN-US" style="color: red;">Pseudo Terminal</span><span style="font-family: 宋体; color: red;">)是成对的逻辑终端设备</span><span style="font-family: 宋体;">,并存在成对的设备文件,如</span><span lang="EN-US">/dev/<span style="color: blue;">ptyp3</span></span><span style="font-family: 宋体;">和</span><span lang="EN-US">/dev/<span style="color: blue;">ttyp3</span></span><span style="font-family: 宋体;">,它们与实际物理设备并不直接相关。如果一个程序把</span><span lang="EN-US">ttyp3</span><span style="font-family: 宋体;">看作是一个串行端口设备,则它对该端口的读</span><span lang="EN-US">/</span><span style="font-family: 宋体;">写操作会反映在该逻辑终端设备对应的</span><span lang="EN-US">ptyp3</span><span style="font-family: 宋体;">上,而</span><span lang="EN-US">ptyp3</span><span style="font-family: 宋体;">则是另一个程序用于读写操作的逻辑设备。这样,两个程序就可以通过这种逻辑设备进行互相交流,使用</span><span lang="EN-US">ttyp3</span><span style="font-family: 宋体;">的程序会认为自己正在与一个串行端口进行通信。</span><span lang="EN-US"> <br /> <span style=""> </span></span><span style="font-family: 宋体;">以</span><span lang="EN-US">telnet </span><span style="font-family: 宋体;">为例,如果某人在使用</span><span lang="EN-US">telnet</span><span style="font-family: 宋体;">程序连接到</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">系统,则</span><span lang="EN-US">telnet</span><span style="font-family: 宋体;">程序就可能会开始连接到设备</span><span lang="EN-US">ptyp2</span><span style="font-family: 宋体;">上,而此时一个</span><span lang="EN-US">getty</span><span style="font-family: 宋体;">程序会运行在对应的</span><span lang="EN-US">ttyp2</span><span style="font-family: 宋体;">端口上。当</span><span lang="EN-US">telnet</span><span style="font-family: 宋体;">从远端获取了一个字符时,该字符就会通过</span><span lang="EN-US">ptyp2</span><span style="font-family: 宋体;">、</span><span lang="EN-US">ttyp2</span><span style="font-family: 宋体;">传递给</span><span lang="EN-US"> getty</span><span style="font-family: 宋体;">程序,而</span><span lang="EN-US">getty</span><span style="font-family: 宋体;">程序则会通过</span><span lang="EN-US">ttyp2</span><span style="font-family: 宋体;">、</span><span lang="EN-US">ptyp2</span><span style="font-family: 宋体;">和</span><span lang="EN-US">telnet</span><span style="font-family: 宋体;">程序返回</span><span lang="EN-US">“login:”</span><span style="font-family: 宋体;">字符串信息。这样,登录程序与</span><span lang="EN-US">telnet</span><span style="font-family: 宋体;">程序</span> <span style="font-family: 宋体;">就通过伪终端进行通信。通过使用适当的软件,可以把</span><span lang="EN-US">2</span><span style="font-family: 宋体;">个或多个伪终端设备连接到同一个物理串行端口上。</span><span lang="EN-US"><br /> <strong style=""><span style="color: red;">3.</span></strong></span><strong style=""><span style="font-family: 宋体; color: red;">控制台终端</span></strong><strong style=""><span style="font-family: 宋体; color: blue;">(</span><span lang="EN-US" style="color: blue;">/dev/ttyn, /dev/console</span></strong><strong style=""><span style="font-family: 宋体; color: blue;">)</span><span lang="EN-US" style="color: red;"><br /> <span style=""> </span></span></strong><span style="font-family: 宋体;">如果当前进程有控制终端(</span><span lang="EN-US">Controlling Terminal</span><span style="font-family: 宋体;">)的话,那么</span><span lang="EN-US" style="color: blue;">/dev/tty</span><span style="font-family: 宋体;">就是当前进程的控制终端的设备特殊文件。可以使用命令</span><span lang="EN-US">“<span style="color: blue;">ps –ax</span>”</span><span style="font-family: 宋体;">来查看进程与哪个控制终端相连使用命令</span><span lang="EN-US">“<span style="color: blue;">tty</span>”</span><span style="font-family: 宋体;">可以查看它具体对应哪个实际终端设备。</span><span lang="EN-US">/dev/tty</span><span style="font-family: 宋体;">有些类似于到实际所使用终端设备的一个联接。</span><span lang="EN-US"><br /> <span style=""> </span></span><span style="font-family: 宋体;">在</span><span lang="EN-US">UNIX</span><span style="font-family: 宋体;">系统中,计算机显示器通常被称为控制台终端(</span><span lang="EN-US">Console</span><span style="font-family: 宋体;">)。它仿真了类型为</span><span lang="EN-US">Linux</span><span style="font-family: 宋体;">的一种终端(</span><span lang="EN-US">TERM=Linux</span><span style="font-family: 宋体;">),并且有一些设备特殊文件与之相关联:</span><span lang="EN-US" style="color: blue;">tty0</span><span style="font-family: 宋体; color: blue;">、</span><span lang="EN-US" style="color: blue;">tty1</span><span style="font-family: 宋体; color: blue;">、</span><span lang="EN-US" style="color: blue;">tty2</span><span style="font-family: 宋体;">等。当用户在控制台上登录时,使用的是</span><span lang="EN-US">tty1</span><span style="font-family: 宋体;">。使用</span><span lang="EN-US" style="color: blue;">Alt+[F1—F6]</span><span style="font-family: 宋体;">组合键时,我们就可以切换到</span><span lang="EN-US">tty2</span><span style="font-family: 宋体;">、</span><span lang="EN-US">tty3</span><span style="font-family: 宋体;">等上面去。</span><span lang="EN-US" style="color: red;">tty1–tty6</span><span style="font-family: 宋体; color: red;">等称为虚拟终端,而</span><span lang="EN-US" style="color: red;">tty0</span><span style="font-family: 宋体; color: red;">则是当前所使用虚拟终端的一个别名,</span><span style="font-family: 宋体;">系统所产生的信息会发送到该终端上。因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。用户可以登录到不同的虚拟终端上去,因而可以让系统同时有几个不同的会话期存在。<span style="color: red;">只有系统或超级用户</span></span><span lang="EN-US" style="color: red;">root</span><span style="font-family: 宋体; color: red;">可以向</span><span lang="EN-US" style="color: red;">/dev/tty0</span><span style="font-family: 宋体; color: red;">进行写操作。</span><span lang="EN-US"><br /> </span><span style="font-family: 宋体;">在</span><span lang="EN-US">Linux </span><span style="font-family: 宋体;">中,可以在系统启动命令行里指定当前的输出终端,格式如下:</span><span lang="EN-US"><br /> <span style="color: blue;">console=device, options</span><br /> device</span><span style="font-family: 宋体;">指代的是终端设备,可以是</span><span lang="EN-US">tty0</span><span style="font-family: 宋体;">(前台的虚拟终端)、</span><span lang="EN-US">ttyX</span><span style="font-family: 宋体;">(第</span><span lang="EN-US">X</span><span style="font-family: 宋体;">个虚拟终端)、</span><span lang="EN-US">ttySX</span><span style="font-family: 宋体;">(第</span><span lang="EN-US">X</span><span style="font-family: 宋体;">个串口)、</span><span lang="EN-US">lp0</span><span style="font-family: 宋体;">(第一个并口)等。</span><span lang="EN-US">options</span><span style="font-family: 宋体;">指代对</span><span lang="EN-US">device</span><span style="font-family: 宋体;">进行的设置,它取决于具体的设备驱动。对于串口设备,参数用来定义为:波特率、校验位、位数,格式为</span><span lang="EN-US">BBBBPN</span><span style="font-family: 宋体;">,其中</span><span lang="EN-US">BBBB</span><span style="font-family: 宋体;">表示波特率,</span><span lang="EN-US">P</span><span style="font-family: 宋体;">表示校验(</span><span lang="EN-US">n/o/e</span><span style="font-family: 宋体;">),</span><span lang="EN-US">N</span><span style="font-family: 宋体;">表示位数,默认</span><span lang="EN-US">options</span><span style="font-family: 宋体;">是</span><span lang="EN-US">9600n8</span><span style="font-family: 宋体;">。</span><span lang="EN-US"><br /> <span style=""> </span></span><span style="font-family: 宋体;">用户可以在内核命令行中同时设定多个终端,这样输出将会在所有的终端上显示,而当用户调用</span><span lang="EN-US">open()</span><span style="font-family: 宋体;">打开</span><span lang="EN-US">/dev/console</span><span style="font-family: 宋体;">时,最后一个终端将会返回作为当前值。例如:</span><span lang="EN-US"><br /> console=ttyS1, 9600 console=tty0<br /> </span><span style="font-family: 宋体;">定义了</span><span lang="EN-US">2</span><span style="font-family: 宋体;">个终端,而调用</span><span lang="EN-US">open()</span><span style="font-family: 宋体;">打开</span><span lang="EN-US">/dev/console</span><span style="font-family: 宋体;">时,将使用虚拟终端</span><span lang="EN-US">tty0</span><span style="font-family: 宋体;">。但是内核消息会在</span><span lang="EN-US">tty0 VGA</span><span style="font-family: 宋体;">虚拟终端和串口</span><span lang="EN-US">ttyS1</span><span style="font-family: 宋体;">上同时显示。</span><span lang="EN-US"><br /> <span style=""> </span></span><span style="font-family: 宋体;">通过查看</span><span lang="EN-US" style="color: blue;">/proc/tty/drivers</span><span style="font-family: 宋体;">文件可以获知什么类型的</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">设备存在以及什么驱动被加载到内核,这个文件包括一个当前存在的不同</span><span lang="EN-US"> tty </span><span style="font-family: 宋体;">驱动的列表,包括驱动名、缺省的节点名、驱动的主编号、这个驱动使用的次编号范围,以及</span><span lang="EN-US"> tty </span><span style="font-family: 宋体;">驱动的类型。例如,下面给出了一个</span><span lang="EN-US">/proc/tty/drivers</span><span style="font-family: 宋体;">文件的例子:</span><span lang="EN-US"><br /> <br /> <strong style="">14.2</strong></span><strong style=""><span style="font-family: 宋体;">终端设备驱动结构</span><span lang="EN-US"><br /> <span style=""> </span></span></strong><span lang="EN-US">Linux</span><span style="font-family: 宋体;">内核中</span><span lang="EN-US"> tty</span><span style="font-family: 宋体;">的层次结构如图</span><span lang="EN-US">14.1</span><span style="font-family: 宋体;">所示<strong style=""><span style="color: red;">,包含</span></strong></span><strong style=""><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">核心、</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">线路规程和</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">驱动</span></strong><span style="font-family: 宋体;">,</span><span lang="EN-US" style="color: red;">tty </span><span style="font-family: 宋体; color: red;">线路规程的工作是以特殊的方式格式化从一个用户或者硬件收到的数据,这种格式化常常采用一个协议转换的形式,</span><span style="font-family: 宋体;">例如</span><span lang="EN-US"> PPP </span><span style="font-family: 宋体;">和</span><span lang="EN-US"> Bluetooth</span><span style="font-family: 宋体;">。</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">设备发送数据的流程为:</span><strong style=""><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">核心从一个用户获取将要发送给一个</span><span lang="EN-US" style="color: red;"> tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">设备的数据,</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">核心将数据传递给</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">线路规程驱动,接着数据被传递到</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">驱动,</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">驱动将数据转换为可以发送给硬件的格式。接收数据的流程为:</span><span style="color: red;"> </span></strong><strong style=""><span style="font-family: 宋体; color: red;">从</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">硬件接收到的数据向上交给</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">驱动,进入</span><span lang="EN-US" style="color: red;">tty</span></strong><strong style=""><span style="font-family: 宋体; color: red;">线路规程驱动,再进入</span><span lang="EN-US" style="color: red;"> tty </span></strong><strong style=""><span style="font-family: 宋体; color: red;">核心,在这里它被一个用户获取。</span></strong><span style="font-family: 宋体;">尽管大多数时候</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">核心和</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">之间的数据传输会经历</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">线路规程的转换,但是</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动与</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">核心之间也可以直接传输数据。</span><span lang="EN-US"><br /> <span style=""> </span><span style=""> </span> <!--[if gte vml 1]><v:shapetypeid="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter" /><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0" /><v:f eqn="sum @0 1 0" /><v:f eqn="sum 0 0 @1" /><v:f eqn="prod @2 1 2" /><v:f eqn="prod @3 21600 pixelWidth" /><v:f eqn="prod @3 21600 pixelHeight" /><v:f eqn="sum @0 0 1" /><v:f eqn="prod @6 1 2" /><v:f eqn="prod @7 21600 pixelWidth" /><v:f eqn="sum @8 21600 0" /><v:f eqn="prod @7 21600 pixelHeight" /><v:f eqn="sum @10 21600 0" /></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /><o:lock v:ext="edit" aspectratio="t" /></v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" alt="" style='width:241.8pt;height:156.6pt;mso-wrap-distance-top:3.75pt;mso-wrap-distance-bottom:3.75pt'><v:imagedata src="file:///C:\DOCUME~1\YUJIAN~1.CHE\LOCALS~1\Temp\msohtml1\03\clip_image001.jpg"o:href="http://www.linuxdriver.cn/html/200710/20071022112258_792.gif" /></v:shape><![endif]--><!--[if !vml]--><img width="322" vspace="5" height="209" v:shapes="_x0000_i1025" src="file:///C:/DOCUME~1/YUJIAN~1.CHE/LOCALS~1/Temp/msohtml1/03/clip_image001.jpg" alt="" /><!--[endif]--><br /> </span><span lang="EN-US" style="font-size: 9pt;"><span style=""> </span><span style=""> </span><span style=""> </span></span><span style="font-size: 9pt; font-family: 宋体;">图</span><span lang="EN-US" style="font-size: 9pt;">14.1 tty</span><span style="font-size: 9pt; font-family: 宋体;">分层结构</span><span lang="EN-US" style="font-size: 9pt;"><br /> </span><span lang="EN-US"><span style=""> </span><span style=""> </span></span><span style="font-family: 宋体;">图</span><span lang="EN-US">14.2</span><span style="font-family: 宋体;">显示了与</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">相关的主要源文件及数据的流向。</span><span lang="EN-US">tty_io.c</span><span style="font-family: 宋体;">定义了</span><span lang="EN-US">tty </span><span style="font-family: 宋体;">设备通用的</span><span lang="EN-US">file_operations</span><span style="font-family: 宋体;">结构体并实现了接口函数</span><span lang="EN-US">tty_register_driver()</span><span style="font-family: 宋体;">用于注册</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">设备,它会利用</span><span lang="EN-US"> fs/char_dev.c</span><span style="font-family: 宋体;">提供的接口函数注册字符设备,与具体设备对应的</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动将实现</span><span lang="EN-US">tty_driver</span><span style="font-family: 宋体;">结构体中的成员函数。同时</span><span lang="EN-US"> tty_io.c</span><span style="font-family: 宋体;">也提供了</span><span lang="EN-US">tty_register_ldisc()</span><span style="font-family: 宋体;">接口函数用于注册线路规程,</span><span lang="EN-US">n_tty.c</span><span style="font-family: 宋体;">文件则实现了</span><span lang="EN-US">tty_disc</span><span style="font-family: 宋体;">结构体中的成员。</span><span lang="EN-US"><br /> <span style=""> </span><span style=""> </span><a target="_blank" href="http://www.linuxdriver.cn/html/200710/20071022112343_751.gif"><!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75"alt="" style='width:337.8pt;height:208.2pt;mso-wrap-distance-top:3.75pt;mso-wrap-distance-bottom:3.75pt' o:button="t"><v:imagedata src="file:///C:\DOCUME~1\YUJIAN~1.CHE\LOCALS~1\Temp\msohtml1\03\clip_image002.jpg"o:href="http://www.linuxdriver.cn/html/200710/20071022112343_751.gif" /></v:shape><![endif]--><!--[if !vml]--><img width="450" vspace="5" height="278" border="0" v:shapes="_x0000_i1026" src="file:///C:/DOCUME~1/YUJIAN~1.CHE/LOCALS~1/Temp/msohtml1/03/clip_image002.jpg" alt="" /><!--[endif]--></a></span></p><p align="left" style="margin: 0cm 7.65pt 0.0001pt 8.9pt; text-align: left; text-indent: 184.5pt;" class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">图</span><span lang="EN-US" style="font-size: 9pt;">14.2 tty</span><span style="font-size: 9pt; font-family: 宋体;">主要源文件关系及数据流向</span><span lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p><p align="left" style="margin: 0cm 7.65pt 0.0001pt 8.9pt; text-align: left; text-indent: 26.25pt;" class="MsoNormal"><span style="font-family: 宋体;">从图</span><span lang="EN-US">14.2</span><span style="font-family: 宋体;">可以看出,<span style="color: red;">特定</span></span><span lang="EN-US" style="color: red;">tty</span><span style="font-family: 宋体; color: red;">设备驱动的主体工作是填充</span><span lang="EN-US" style="color: red;">tty_driver</span><span style="font-family: 宋体; color: red;">结构体中的成员</span><span style="font-family: 宋体;">,实现其中的成员函数,</span><span lang="EN-US">tty_driver</span><span style="font-family: 宋体;">结构体的定义如代码清单</span><span lang="EN-US">14.1</span><span style="font-family: 宋体;">。</span><span lang="EN-US"><br /> </span><span style="font-family: 宋体;">代码清单</span><span lang="EN-US">14.1 tty_driver</span><span style="font-family: 宋体;">结构体</span><span lang="EN-US"><br /> 1<span style="color: blue;"> struct tty_driver</span> <br /> 2 { <br /> 3 int magic; <br /> 4 struct cdev cdev; /* </span><span style="font-family: 宋体;">对应的字符设备</span><span lang="EN-US">cdev */ <br /> 5 struct module *owner; /*</span><span style="font-family: 宋体;">这个驱动的模块拥有者</span><span lang="EN-US"> */ <br /> 6 const char *driver_name; <br /> 7 const char *devfs_name; <br /> 8 const char *name; /* </span><span style="font-family: 宋体;">设备名</span><span lang="EN-US"> */ <br /> 9 int name_base; /* offset of printed name */ <br /> 10 int major; /* </span><span style="font-family: 宋体;">主设备号</span><span lang="EN-US"> */ <br /> 11 int minor_start; /* </span><span style="font-family: 宋体;">开始次设备号</span><span lang="EN-US"> */ <br /> 12 int minor_num; /* </span><span style="font-family: 宋体;">设备数量</span><span lang="EN-US"> */ <br /> 13 int num; /* </span><span style="font-family: 宋体;">被分配的设备数量</span><span lang="EN-US"> */ <br /> 14 short type; /* tty</span><span style="font-family: 宋体;">驱动的类型</span><span lang="EN-US"> */ <br /> 15 short subtype; /* tty</span><span style="font-family: 宋体;">驱动的子类型</span><span lang="EN-US"> */ <br /> 16 struct termios init_termios; /* </span><span style="font-family: 宋体;">初始线路设置</span><span lang="EN-US"> */ <br /> 17 int flags; /* tty</span><span style="font-family: 宋体;">驱动标志</span><span lang="EN-US"> */ <br /> 18 int refcount; /*</span><span style="font-family: 宋体;">引用计数(针对可加载的</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动)</span><span lang="EN-US"> */ <br /> 19 struct proc_dir_entry *proc_entry; /* /proc</span><span style="font-family: 宋体;">文件系统入口</span><span lang="EN-US"> */ <br /> 20 struct tty_driver *other; /* </span><span style="font-family: 宋体;">仅对</span><span lang="EN-US">PTY</span><span style="font-family: 宋体;">驱动有意义</span><span lang="EN-US"> */ <br /> 21 ... <br /> 22 /* </span><span style="font-family: 宋体;">接口函数</span><span lang="EN-US"> */ <br /> 23 int(*open)(struct tty_struct *tty, struct file *filp); <br /> 24 void(*close)(struct tty_struct *tty, struct file *filp); <br /> 25 int(*write)(struct tty_struct *tty, const unsigned char *buf, int count); <br /> 26 void(*put_char)(struct tty_struct *tty, unsigned char ch); <br /> 27 void(*flush_chars)(struct tty_struct *tty); <br /> 28 int(*write_room)(struct tty_struct *tty); <br /> 29 int(*chars_in_buffer)(struct tty_struct *tty); <br /> 30 int(*ioctl)(struct tty_struct *tty, struct file *file, unsigned int cmd, <br /> 31 unsigned long arg); <br /> 32 void(*set_termios)(struct tty_struct *tty, struct termios *old); <br /> 33 void(*throttle)(struct tty_struct *tty); <br /> 34 void(*unthrottle)(struct tty_struct *tty); <br /> 35 void(*stop)(struct tty_struct *tty); <br /> 36 void(*start)(struct tty_struct *tty); <br /> 37 void(*hangup)(struct tty_struct *tty); <br /> 38 void(*break_ctl)(struct tty_struct *tty, int state); <br /> 39 void(*flush_buffer)(struct tty_struct *tty); <br /> 40 void(*set_ldisc)(struct tty_struct *tty); <br /> 41 void(*wait_until_sent)(struct tty_struct *tty, int timeout); <br /> 42 void(*send_xchar)(struct tty_struct *tty, char ch); <br /> 43 int(*read_proc)(char *page, char **start, off_t off, int count, int *eof, <br /> 44 void *data); <br /> 45 int(*write_proc)(struct file *file, const char __user *buffer, unsigned long<br /> 46 count, void *data); <br /> 47 int(*tiocmget)(struct tty_struct *tty, struct file *file); <br /> 48 int(*tiocmset)(struct tty_struct *tty, struct file *file, unsigned int set, <br /> 49 unsigned int clear); <br /> 50 <br /> 51 struct list_head tty_drivers; <br /> 52 }; <br /> <span style=""> </span>tty_driver</span><span style="font-family: 宋体;">结构体中的</span><span lang="EN-US">magic</span><span style="font-family: 宋体;">表示给这个结构体的</span><span lang="EN-US">“</span><span style="font-family: 宋体;">幻数</span><span lang="EN-US">”</span><span style="font-family: 宋体;">,设为</span><span lang="EN-US"> TTY_DRIVER_MAGIC</span><span style="font-family: 宋体;">,在</span> <span lang="EN-US" style="color: blue;">alloc_tty_driver()</span><span style="font-family: 宋体;">函数中被初始化。</span><span lang="EN-US" style="color: red;">name</span><span style="font-family: 宋体; color: red;">与</span><span lang="EN-US" style="color: red;">driver_name</span><span style="font-family: 宋体; color: red;">的不同在于后者表示驱动的名字,用在</span><span lang="EN-US" style="color: red;"> /proc/tty </span><span style="font-family: 宋体; color: red;">和</span><span lang="EN-US" style="color: red;"> sysfs</span><span style="font-family: 宋体; color: red;">中,而前者表示驱动的设备节点名</span><span style="font-family: 宋体;">。</span><span lang="EN-US">type </span><span style="font-family: 宋体;">与</span><span lang="EN-US">subtype</span><span style="font-family: 宋体;">描述</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动的类型和子类型,</span><span lang="EN-US">subtype</span><span style="font-family: 宋体;">的值依赖于</span><span lang="EN-US">type</span><span style="font-family: 宋体;">,</span><span lang="EN-US">type</span><span style="font-family: 宋体;">成员的可能值为</span><span lang="EN-US"> TTY_DRIVER_TYPE_SYSTEM</span><span style="font-family: 宋体;">(由</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">子系统内部使用,</span><span lang="EN-US">subtype </span><span style="font-family: 宋体;">应当设为</span><span lang="EN-US"> SYSTEM_TYPE_TTY</span><span style="font-family: 宋体;">、</span><span lang="EN-US">SYSTEM_TYEP_CONSOLE</span><span style="font-family: 宋体;">、</span><span lang="EN-US">SYSTEM_TYPE_SYSCONS</span><span style="font-family: 宋体;">或</span><span lang="EN-US"> SYSTEM_TYPE_SYSPTMX</span><span style="font-family: 宋体;">,这个类型不应当被任何常规</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动使用)、</span><span lang="EN-US">TTY_DRIVER_TYPE_CONSOLE</span><span style="font-family: 宋体;">(仅被控制台驱动使用)、</span><span lang="EN-US">TTY_DRIVER_TYPE_SERIAL</span><span style="font-family: 宋体;">(被任何串行类型驱动使用,</span><span lang="EN-US">subtype </span><span style="font-family: 宋体;">应当设为</span><span lang="EN-US"> SERIAL_TYPE_NORMAL </span><span style="font-family: 宋体;">或</span><span lang="EN-US">SERIAL_TYPE_CALLOUT</span><span style="font-family: 宋体;">)、</span><span lang="EN-US">TTY_DRIVER_TYPE_PTY</span><span style="font-family: 宋体;">(被伪控制台接口</span><span lang="EN-US">pty</span><span style="font-family: 宋体;">使用,此时</span><span lang="EN-US">subtype</span><span style="font-family: 宋体;">需要被设置为</span><span lang="EN-US"> PTY_TYPE_MASTER </span><span style="font-family: 宋体;">或</span><span lang="EN-US"> PTY_TYPE_SLAVE</span><span style="font-family: 宋体;">)。</span><span lang="EN-US">init_termios </span><span style="font-family: 宋体;">为初始线路设置,为一个</span><span lang="EN-US">termios</span><span style="font-family: 宋体;">结构体,这个成员被用来提供一个线路设置集合。</span><span lang="EN-US" style="color: blue;">termios</span><span lang="EN-US"> </span><span style="font-family: 宋体;">用于保存当前的线路设置,这些线路设置控制当前波特率、数据大小、数据流控设置等,这个结构体包含</span><span lang="EN-US">tcflag_t c_iflag</span><span style="font-family: 宋体;">(输入模式标志)、</span><span lang="EN-US">tcflag_t c_oflag</span><span style="font-family: 宋体;">(输出模式标志)、</span><span lang="EN-US">tcflag_t c_cflag</span><span style="font-family: 宋体;">(控制模式标志)、</span><span lang="EN-US">tcflag_t c_lflag</span><span style="font-family: 宋体;">(本地模式标志)、</span><span lang="EN-US">cc_t c_line</span><span style="font-family: 宋体;">(线路规程类型)、</span><span lang="EN-US">cc_t c_cc[NCCS]</span><span style="font-family: 宋体;">(一个控制字符数组)等成员。驱动会使用一个标准的数值集初始化这个成员,它拷贝自</span><span lang="EN-US">tty_std_termios</span><span style="font-family: 宋体;">变量,</span><span lang="EN-US">tty_std_termos</span><span style="font-family: 宋体;">在</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">核心中的定义如代码清单</span><span lang="EN-US">14.2</span><span style="font-family: 宋体;">。</span><span lang="EN-US"><br /> </span><span style="font-family: 宋体;">代码清单</span><span lang="EN-US">14.2 tty_std_termios</span><span style="font-family: 宋体;">变量</span><span lang="EN-US"><br /> 1 struct termios tty_std_termios = <br /> 2 {<br /> 3 .c_iflag = ICRNL | IXON, /* </span><span style="font-family: 宋体;">输入模式</span><span lang="EN-US"> */<br /> 4 .c_oflag = OPOST | ONLCR, /* </span><span style="font-family: 宋体;">输出模式</span><span lang="EN-US"> */<br /> 5 .c_cflag = B38400 | CS8 | CREAD | HUPCL, /* </span><span style="font-family: 宋体;">控制模式</span><span lang="EN-US"> */<br /> 6 .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |<br /> 7 ECHOCTL | ECHOKE | IEXTEN, /* </span><span style="font-family: 宋体;">本地模式</span><span lang="EN-US"> */<br /> 8 .c_cc = INIT_C_CC /* </span><span style="font-family: 宋体;">控制字符,用来修改终端的特殊字符映射</span><span lang="EN-US"> */<br /> 9 };<br /> <span style=""> </span>tty_driver </span><span style="font-family: 宋体;">结构体中的</span><span lang="EN-US">major</span><span style="font-family: 宋体;">、</span><span lang="EN-US">minor_start</span><span style="font-family: 宋体;">、</span><span lang="EN-US">minor_num</span><span style="font-family: 宋体;">表示主设备号、次设备号及可能的次设备数,</span><span lang="EN-US">name</span><span style="font-family: 宋体;">表示设备名(如</span><span lang="EN-US">ttyS</span><span style="font-family: 宋体;">),第</span><span lang="EN-US"> 23</span><span style="font-family: 宋体;">~</span><span lang="EN-US">49</span><span style="font-family: 宋体;">行的函数指针实际和</span><span lang="EN-US">tty_operations</span><span style="font-family: 宋体;">结构体等同,它们通常需在特定设备</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">驱动模块初始化函数中被赋值。</span><span lang="EN-US">put_char()</span><span style="font-family: 宋体;">为单字节写函数,当单个字节被写入设备时这个函数被</span><span lang="EN-US"> tty </span><span style="font-family: 宋体;">核心调用,如果一个</span><span lang="EN-US"> tty </span><span style="font-family: 宋体;">驱动没有定义这个函数,将使用</span><span lang="EN-US">count</span><span style="font-family: 宋体;">参数为</span><span lang="EN-US">1</span><span style="font-family: 宋体;">的</span><span lang="EN-US">write()</span><span style="font-family: 宋体;">函数。</span><span lang="EN-US">flush_chars()</span><span style="font-family: 宋体;">与</span><span lang="EN-US">wait_until_sent()</span><span style="font-family: 宋体;">函数都用于刷新数据到硬件。</span><span lang="EN-US">write_room()</span><span style="font-family: 宋体;">指示有多少缓冲区空闲,</span><span lang="EN-US">chars_in_buffer()</span><span style="font-family: 宋体;">指示缓冲区中包含的数据数。当</span><span lang="EN-US"> ioctl(2)</span><span style="font-family: 宋体;">在设备节点上被调用时,</span><span lang="EN-US">ioctl()</span><span style="font-family: 宋体;">函数将被</span><span lang="EN-US"> tty</span><span style="font-family: 宋体;">核心调用。当设备的</span><span lang="EN-US"> termios </span><span style="font-family: 宋体;">设置被改变时,</span><span lang="EN-US">set_termios()</span><span style="font-family: 宋体;">函数将被</span><span lang="EN-US">tty</span><span style="font-family: 宋体;">核心调用。</span><span lang="EN-US">throttle ()</span><span style="font-family: 宋体;">、</span><span lang="EN-US">unthrottle()</span><span style="font-family: 宋体;">、</span><span lang="EN-US">stop()</span><span style="font-family: 宋体;">和</span><span lang="EN-US">start()</span><span style="font-family: 宋体;">为数据抑制函数,这些函数用来帮助控制</span><span lang="EN-US"> tty </span><span style="font-family: 宋体;">核心的输入缓存。<span style="color: red;">当</span></span><span lang="EN-US" style="color: red;"> tty </span><span style="font-family: 宋体; color: red;">核心的输入缓冲满时,</span><span lang="EN-US" style="color: red;">throttle()</span><span style="font-family: 宋体; color: red;">函数将被调用,</span><span lang="EN-US" style="color: red;">tty</span><span style="font-family: 宋体; color: red;">驱动试图通知设备不应当发送字符给它。当</span><span lang="EN-US" style="color: red;"> tty </span><span style="font-family: 宋体; color: red;">核心的输入缓冲已被清空时,</span><span lang="EN-US" style="color: red;">unthrottle()</span><span style="font-family: 宋体; color: red;">函数将被调用暗示设备可以接收数据。</span><span lang="EN-US" style="color: red;">stop()</span><span style="font-family: 宋体; color: red;">和</span><span lang="EN-US" style="color: red;">start()</span><span style="font-family: 宋体; color: red;">函数非常像</span><span lang="EN-US" style="color: red;">throttle()</span><span style="font-family: 宋体; color: red;">和</span><span lang="EN-US" style="color: red;"> unthrottle()</span><span style="font-family: 宋体; color: red;">函数,但它们表示</span><span lang="EN-US" style="color: red;"> tty </span><span style="font-family: 宋体; color: red;">驱动应当停止发送数据给设备以及恢复发送数据。</span><span lang="EN-US"><br /> <span style=""> </span></span><span style="font-family: 宋体;">当</span><span lang="EN-US"> tty</span><span style="font-family: 宋体;">驱动挂起</span><span lang="EN-US"> tty</span><span style="font-family: 宋体;">设备时,</span><span lang="EN-US">hangup()</span><span style="font-family: 宋体;">函数被调用,在此函数中进行相关的硬件操作。当</span><span lang="EN-US">tty </span><span style="font-family: 宋体;">驱动要在</span><span lang="EN-US"> RS-232 </span><span style="font-family: 宋体;">端口上打开或关闭线路的</span><span lang="EN-US"> BREAK </span><span style="font-family: 宋体;">状态时,</span><span lang="EN-US">break_ctl()</span><span style="font-family: 宋体;">线路中断控制函数被调用。如果</span><span lang="EN-US">state</span><span style="font-family: 宋体;">状态设为</span><span lang
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -