zoukankan      html  css  js  c++  java
  • tty_alloc_driver

      /inclue/linux/tty_driver.h

    /* Use TTY_DRIVER_* flags below */
    #define tty_alloc_driver(lines, flags) \
                    __tty_alloc_driver(lines, THIS_MODULE, flags)
    /*
     * DEPRECATED Do not use this in new code, use tty_alloc_driver instead.
     * 不赞成使用这个新代码,通常使用tty_alloc_driver来代替。其实他们实际意义是一样的
     * (And change the return value checks.)
     */
    static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
    {
        struct tty_driver *ret = tty_alloc_driver(lines, 0);
    //当看到代码中调用alloc_tty_driver时,flag默认为0
        if (IS_ERR(ret))
            return NULL;
        return ret;
    }
    ----------------------------------------------------------------------
    /*
     * tty driver flags
     *   
     * TTY_DRIVER_RESET_TERMIOS --- requests the tty layer to reset the
     *      termios setting when the last process has closed the device.
     *      Used for PTY's, in particular.
     * 当设备关闭时,请求复位termios。通常使用PTY
     * 
     * TTY_DRIVER_REAL_RAW --- if set, indicates that the driver will
     *      guarantee never not to set any special character handling
     *      flags if ((IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR ||
     *      !INPCK)).  That is, if there is no reason for the driver to
     *      send notifications of parity and break characters up to the
     *      line driver, it won't do so.  This allows the line driver to
     *      optimize for this case if this flag is set.  (Note that there
     *      is also a promise, if the above case is true, not to signal
     *      overruns, either.)
     * 如果设置,驱动将不会设置任何特殊的字符处理标志 
     * 意味着,如果没有原因,驱动将不会将通知送给线驱动
     * 如果设置了,可以使线驱动优化这一处理程序
     *
     * TTY_DRIVER_DYNAMIC_DEV --- if set, the individual tty devices need
     *      to be registered with a call to tty_register_device() when the
     *      device is found in the system and unregistered with a call to
     *      tty_unregister_device() so the devices will be show up
     *      properly in sysfs.  If not set, driver->num entries will be
     *      created by the tty core in sysfs when tty_register_driver() is
     *      called.  This is to be used by drivers that have tty devices
     *      that can appear and disappear while the main tty driver is
     *      registered with the tty core.
     * 如果设置,特别的tty设备将在其被发现时注册 和 调用注销函数时注销
     * 如果不设置,当注册函数被调用时,sysfs的tty核心层会自动创建driver->num
     * 这个flag通常使用在主tty驱动被tty核心注册,且tty设备可能出现和消失
     * 
     * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
     *      use dynamic memory keyed through the devpts filesystem.  This
     *      is only applicable to the pty driver.
     * 不使用标准数组, 而是使用devpts文件系统的动态记忆链
     * 这个是给pty驱动使用的
     *
     * TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass
     *      the requested timeout to the caller instead of using a simple
     *      on/off interface.
     * 硬件处理断点信号。发送暂时休息(timeout)请求而不是简单地打开/关闭接口
     *
     * TTY_DRIVER_DYNAMIC_ALLOC -- do not allocate structures which are
     *      needed per line for this driver as it would waste memory.
     *      The driver will take care.
     * 不每条线都分配结构,因其会浪费内存。使用这个flag,驱动将注意这一情况
     *
     * TTY_DRIVER_UNNUMBERED_NODE -- do not create numbered /dev nodes. In
     *      other words create /dev/ttyprintk and not /dev/ttyprintk0.
     *      Applicable only when a driver for a single tty device is
     *      being allocated.
     * 不创建已经分配的/dev节点。
     * 意思是创建/dev/ttyprintk 而非创建/dev/ttyprintk0
     * 只用在一个驱动为了一个单独的且已经被分配tty设备注册时
     */
    #define TTY_DRIVER_INSTALLED            0x0001
    #define TTY_DRIVER_RESET_TERMIOS        0x0002
    #define TTY_DRIVER_REAL_RAW             0x0004
    #define TTY_DRIVER_DYNAMIC_DEV          0x0008
    #define TTY_DRIVER_DEVPTS_MEM           0x0010
    #define TTY_DRIVER_HARDWARE_BREAK       0x0020
    #define TTY_DRIVER_DYNAMIC_ALLOC        0x0040
    #define TTY_DRIVER_UNNUMBERED_NODE      0x0080

      在看分配函数之前,先来看一下tty_driver这个结构体

      /include/linux/tty/tty_driver.h

    struct tty_driver {
        int     magic;          /* magic number for this structure */
        struct kref kref;       /* Reference management */
        struct cdev *cdevs;
        struct module   *owner;
        const char      *driver_name;
        const char      *name;
        int     name_base;      /* offset of printed name */
        int     major;          /* major device number */
        int     minor_start;    /* start of minor device number */
        unsigned int    num;    /* number of devices allocated */
        short   type;           /* type of tty driver */
        short   subtype;        /* subtype of tty driver */
        struct ktermios init_termios; /* Initial termios */
        unsigned long   flags;          /* tty driver flags */
        struct proc_dir_entry *proc_entry; /* /proc fs entry */
        struct tty_driver *other; /* only used for the PTY driver */
    
        /*
         * Pointer to the tty data structures
         */
        struct tty_struct **ttys;
        struct tty_port **ports;
        struct ktermios **termios;
        void *driver_state;
    
        /*
         * Driver methods
         */
    
        const struct tty_operations *ops;
        struct list_head tty_drivers;
    };

       分配tty驱动函数

      /drivers/tty/tty_io.c

    /**
     * __tty_alloc_driver -- allocate tty driver
     * @lines: count of lines this driver can handle at most
     * @owner: module which is repsonsible for this driver
     * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags
     *
     * This should not be called directly, some of the provided macros should be
     * used instead. Use IS_ERR and friends on @retval.
     */
    struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
            unsigned long flags)
    {
        struct tty_driver *driver;
        unsigned int cdevs = 1;
        int err;
    
        if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))
    //The priority is '&' higher than '&&'
    //当设置flag为TTY_DRIVER_UNNUMBERD_NODE或lines为0的时候,返回-EINVAL
    //means -E(rror)IN(put)VAL(ue)
            return ERR_PTR(-EINVAL);
    
        driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
        if (!driver)  //若分配失败,返回-ENOMEM
            return ERR_PTR(-ENOMEM);
    
        kref_init(&driver->kref);
        driver->magic = TTY_DRIVER_MAGIC;
        driver->num = lines;
        driver->owner = owner;
        driver->flags = flags;
    
    //看看声明的flags有什么特点就知道这个 & 的作用了
        if (!(flags & TTY_DRIVER_DEVPTS_MEM)) {
    //若没设置TTY_DRIVER_DEVPTS_MEM
    //使用标准数组
            driver->ttys = kcalloc(lines, sizeof(*driver->ttys),
                    GFP_KERNEL);
    //定义为struct tty_struct **tty, kcalloc分配成功返回0
            driver->termios = kcalloc(lines, sizeof(*driver->termios),
                    GFP_KERNEL);
    //定义为struct ktermios **termios
            if (!driver->ttys || !driver->termios) {
    //ttys和termios任一成功才继续往下
                err = -ENOMEM;
                goto err_free_all;
            }
        }
    
        if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
    //若没设置TTY_DRIVER_DYNAMIC_ALLOC, 则为每条线都分配结构
            driver->ports = kcalloc(lines, sizeof(*driver->ports),
                    GFP_KERNEL);
            if (!driver->ports) {
                err = -ENOMEM;
                goto err_free_all;
            }
            cdevs = lines;
        }
    
        driver->cdevs = kcalloc(cdevs, sizeof(*driver->cdevs), GFP_KERNEL);
        if (!driver->cdevs) {
            err = -ENOMEM;
            goto err_free_all;
        }
    
        return driver;
    err_free_all:
        kfree(driver->ports);
        kfree(driver->ttys);
        kfree(driver->termios);
        kfree(driver);
        return ERR_PTR(err);
    }
    EXPORT_SYMBOL(__tty_alloc_driver);
    
    
  • 相关阅读:
    什么是先进先出淘汰算法,试举出一种实现方法?
    什么是置换算法,在页式系统中常用的置换算法是什么?
    什么是系统的抖动,它有什么危害?
    如果主存中的某页正在与外部设备交换信息,缺页中断时可以将这一页淘汰吗?为了实现正确的页面调度,应如何扩充页表的功能?
    什么是虚拟存储器,在页式系统中如何实现虚拟存储?
    分区分配方法的主要缺点是什么,如何克服这一缺点?
    什么是最坏适应算法?该算法的特点是什么?
    什么是最佳适应算法,该算法的特点是什么?
    JAVA8 之初识函数式编程与函数式接口(一)
    使用 Netty 实现一个 MVC 框架
  • 原文地址:https://www.cnblogs.com/plinx/p/2910782.html
Copyright © 2011-2022 走看看