⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch18s02.html

📁 驱动程序在 Linux 内核里扮演着特殊的角色. 它们是截然不同的"黑盒子", 使硬件的特殊的一部分响应定义好的内部编程接口. 它们完全隐藏了设备工作的细节. 用户的活动通过一套标准化的调用来进行,
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>18.2.&#160;tty_driver 函数指针-Linux设备驱动第三版(中文版)-开发频道-华星在线</title>
<meta name="description" content="驱动开发-开发频道-华星在线" />
<meta name="keywords" content="Linux设备驱动,中文版,第三版,ldd,linux device driver,驱动开发,电子版,程序设计,软件开发,开发频道" />
<meta name="author" content="华星在线 www.21cstar.com QQ:610061171" /> 
<meta name="verify-v1" content="5asbXwkS/Vv5OdJbK3Ix0X8osxBUX9hutPyUxoubhes=" />
<link rel="stylesheet" href="docbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.69.0">
<link rel="start" href="index.html" title="Linux 设备驱动 Edition 3">
<link rel="up" href="ch18.html" title="第&#160;18&#160;章&#160;TTY 驱动">
<link rel="prev" href="ch18.html" title="第&#160;18&#160;章&#160;TTY 驱动">
<link rel="next" href="ch18s03.html" title="18.3.&#160;TTY 线路设置">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">18.2.&#160;tty_driver 函数指针</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="ch18.html">上一页</a>&#160;</td>
<th width="60%" align="center">第&#160;18&#160;章&#160;TTY 驱动</th>
<td width="20%" align="right">&#160;<a accesskey="n" href="ch18s03.html">下一页</a>
</td>
</tr>
</table>
<hr>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="ttydriverFunctionPointers.sect"></a>18.2.&#160;tty_driver 函数指针</h2></div></div></div>
<p>最终, tiny_tty 驱动声明了 4 个函数指针.</p>
<div class="sect2" lang="zh-cn">
<div class="titlepage"><div><div><h3 class="title">
<a name="openandclose.sect"></a>18.2.1.&#160;open 和 close</h3></div></div></div>
<p>open 函数被 tty 核心调用, 当一个用户对这个 tty 驱动被分配的设备节点调用 open 时. tty 核心使用一个指向分配给这个设备的 tty_struct 结构的指针调用它, 还用一个文件指针. 这个 open 成员必须被一个 tty 驱动为它能正确工作而设置; 否则, -ENODEV 被返回给用户当调用 open 时.</p>
<p>当调用这个 open 函数, tty 驱动被期望或者保存一些传递给它的 tty_struct 变量中的数据, 或者保存一个可以基于端口次编号来引用的静态数组中的数据. 这是有必要的, 所以 tty 驱动知道哪个设备在被引用当以后的 close, write, 和其他函数被调用时.</p>
<p>tiny_tty 驱动保存一个指针在 tty 结构中, 如同下面代码所见到:</p>
<pre class="programlisting">
static int tiny_open(struct tty_struct *tty, struct file *file)
{
        struct tiny_serial *tiny;
        struct timer_list *timer;
        int index;

        /* initialize the pointer in case something fails */
        tty-&gt;driver_data = NULL;

        /* get the serial object associated with this tty pointer */
        index = tty-&gt;index;
        tiny = tiny_table[index];
        if (tiny == NULL)
        {

                /* first time accessing this device, let's create it */
                tiny = kmalloc(sizeof(*tiny), GFP_KERNEL);
                if (!tiny)

                        return -ENOMEM;
                init_MUTEX(&amp;tiny-&gt;sem);
                tiny-&gt;open_count = 0;
                tiny-&gt;timer = NULL;

                tiny_table[index] = tiny;
        }

        down(&amp;tiny-&gt;sem);
        /* save our structure within the tty structure */
        tty-&gt;driver_data = tiny;
        tiny-&gt;tty = tty;
</pre>
<p>在这个代码中, tiny_serial 结构被保存在 tty 结构中. 这允许 tiny_write, tiny_write_room, 和 tiny_close 函数来获取 tiny_serial 结构和正确操作它.</p>
<p>tiny_serial 结构定义为:</p>
<pre class="programlisting">
struct tiny_serial
{
        struct tty_struct *tty; /* pointer to the tty for this device */
        int open_count; /* number of times this port has been opened */
        struct semaphore  sem;  /* locks this structure */
        struct timer_list  *timer;
};
</pre>
<p>如同我们已见到的, open_count 变量初始化为 0 在第一次打开端口的 open 调用中. 这是一个典型的引用计数, 因为一个 tty 驱动的 open 和 close 函数可能对同一个设备多次调用以便多个进程来读写数据. 为正确处理所有的事情, 必须保持一个这个端口被打开或者关闭的次数计数; 这个驱动递增和递减这个计数在打开使用时. 当打开第一次被打开, 任何必要的硬件初始化和内存分配可以做. 当端口被最后一次关闭, 任何必要的硬件关闭和内存清理可以做.</p>
<p>tiny_open 函数的剩下部分展示了如何跟踪设备被打开的次数:</p>
<pre class="programlisting">
++tiny-&gt;open_count;
if (tiny-&gt;open_count == 1)
{
        /* this is the first time this port is opened */
        /* do any hardware initialization needed here */
</pre>
<p>open 函数必须返回或者一个负的错误号如果发生事情阻止了成功打开, 或者一个 0 来表示成功.</p>
<p>close 函数指针被 tty 核心调用, 在用户对前面使用 open 调用而创建的文件句柄调用 close 时. 这表示设备应当在这次被关闭. 但是, 因为 open 函数可被多次调用, close函数也可多次调用. 因此这个函数应当跟踪它被调用的次数来决定是否硬件应当在此次真正被关闭. tiny_tty 驱动做这个使用下面的代码:</p>
<pre class="programlisting">
static void do_close(struct tiny_serial *tiny)
{
        down(&amp;tiny-&gt;sem);

        if (!tiny-&gt;open_count)
        {
                /* port was never opened */
                goto exit;

        }
        --tiny-&gt;open_count;
        if (tiny-&gt;open_count &lt;= 0)
        {
                /* The port is being closed by the last user. */
                /* Do any hardware specific stuff here */

                /* shut down our timer */
                del_timer(tiny-&gt;timer);
        }
exit:
        up(&amp;tiny-&gt;sem);
}

static void tiny_close(struct tty_struct *tty, struct file *file)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -