tiny4412 串口驱动分析九 --- shell终端

2023-06-25  

开发板:tiny4412ADK+S700 4GB Flash

主机:Wind7 64位

虚拟机:Vmware+Ubuntu12_04

u-boot:U-Boot 2010.12

Linux内核版本:linux-3.0.31

Android版本:android-4.1.2

 

 

在上面我们知道了/dev/ttySACx是如何生成的,此外还可以看到在/dev下还有设备结点/dev/console,以及/dev/tty等设备结点。

 

可以看到向/dev/ttySAC0、/dev/console和/dev/tty输入字符,然后这些字符会输出到串口终端上:

 

但是如果使用adb shell登陆后,现象不同:

其中,左边的窗口是在adb shell下,右边的窗口是串口终端的显示,可以看到如果在adb shell下向 /dev/ttySAC0和 /dev/console下写入字符的话,这个字符并没有在adb shell终端下显示,相反却在串口终端中显示出来,当在adb shell终端下向/dev/tty下写入字符时,就在adb shell终端下显示出来了,并没有影响到串口终端的显示。

上面的这些现象背后的原因是什么呢?下面我们开始分析内核源码来解释。

首先需要知道这些设备结点是怎么生成的:

late_initcall(chr_dev_init);

     ---- tty_init()   (drivers/tty/tty_io.c)

int __init tty_init(void)

{

    cdev_init(&tty_cdev, &tty_fops);

    if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||

        register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)

        panic("Couldn't register /dev/tty drivern");

    device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");


    cdev_init(&console_cdev, &console_fops);

    if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||

        register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)

        panic("Couldn't register /dev/console drivern");

    consdev = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,

                  "console");

    if (IS_ERR(consdev))

        consdev = NULL;

    else

        WARN_ON(device_create_file(consdev, &dev_attr_active) < 0);


    return 0;

}

复制代码

在这里会在/dev/下生成console和tty两个设备结点,他们对应的fops分别是tty_fops和console_fops。


在上面分析的tty_register_device函数会生成/dev/ttySACx,它对应的fops在函数tty_register_driver中设置为了tty_fops。所以这里的关键是分析tty_fops和console_fops是如何实现的。


对比发现,console_fops和tty_fops是一样的:


static const struct file_operations tty_fops = {

    .llseek        = no_llseek,

    .read        = tty_read,

    .write        = tty_write,

    .poll        = tty_poll,

    .unlocked_ioctl    = tty_ioctl,

    .compat_ioctl    = tty_compat_ioctl,

    .open        = tty_open,

    .release    = tty_release,

    .fasync        = tty_fasync,

};


static const struct file_operations console_fops = {

    .llseek        = no_llseek,

    .read        = tty_read,

    .write        = redirected_tty_write,

    .poll        = tty_poll,

    .unlocked_ioctl    = tty_ioctl,

    .compat_ioctl    = tty_compat_ioctl,

    .open        = tty_open,

    .release    = tty_release,

    .fasync        = tty_fasync,

};


执行echo “peng” > /dev/ttySAC0的时候,会先调用tty_open然后调用tty_write,最后调用tty_release。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。