zoukankan      html  css  js  c++  java
  • Linux TTY函数跟踪

    1. 介绍

    本文介绍了TTY打开、TTY读和TTY写操作的函数跟踪过程

    2. 示例

    下面是一个简单的Linux TTY打开和读写过程

    #include <termios.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        struct termios toptions;
        int fd, falgs;
    
        flags = O_RDWR | O_NOCTTY | O_SYNC | O_NDELAY;
        fd = open("/dev/ttyS0", flags);
    
        tcflush(fd, TCIOFLUSH);
        memset(&toptions, 0, sizeof(toptions));
        tcgetattr(fd, &toptions);
        cfmakeraw(&toptions);
    
    tcgetattr(fd, &toptions); cfsetospeed(&toptions, B115200); cfsetispeed(&toptions, B115200); tcgetattr(fd, &toptions); toptions.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD | INPCK; toptions.c_cc[VMIN] = 1; toptions.c_cc[VTIME] = 0; tcflush(fd, TCIOFLUSH); tcsetattr(fd, TCSANOW, &toptions); uint8_t data[64] = { 0x01, 0x09, 0x10, 0x00 }; write(fd, data, 4); memset(read_data, 0, 64); read(fd, data, 64); return 0; }

    3. 打开

    open会调用tty_open, 其分析如下:

    tty_open
      tty_alloc_file
      /* 分配tty_file_private并赋值给file::private_data */
      tty_open_current_tty
      /* 如果当前设备是/dev/tty则尝试重新打开, 通常返回NULL */
      tty_open_by_driver
      /* 如果上面的函数返回NULL通过查找tty驱动打开tty设备 */
        tty_lookup_driver
        /* 根据设备号查找对应的tty驱动 */
        tty_driver_lookup_tty
        /* 根据tty_driver::tty_operations::lookup/tty_driver::tty_struct查找tty_struct是否存在 */
        tty_reopen
        /* 如果tty_struct已分配, 则打开该tty */
          tty_ldisc_reinit
          /* 初始化tty设备的线路规程 */
            tty_ldisc_get
            /* 根据类别(默认为N_TTY)获取注册的对应线路规程, 并分配对应tty_ldisc实例 */
            tty_set_termios_ldisc
            /* 设置该tty的线路规程 */
            tty_ldisc_open
            /* 调用tty_ldisc::tty_ldisc_ops::open, 对于N_TTY为n_tty_open */
        tty_init_dev
        /* 如果tty_struct没有分配则进行分配(!!!uart就是如此!!!) */
          alloc_tty_struct
          /* 分配和初始化一个tty_struct, 包括driver, ops, index等 */
            tty_ldisc_init
            /* 初始化tty_struct的线路规程 */
              tty_ldisc_get
              /* 获取N_TTY对应线路规程, 并分配对应tty_ldisc实例 */ 
            tty_struct::tty_operations = tty_driver::tty_operations
            /* 设置tty_struct的函数操作集 */
          tty_driver_install_tty
          /* 通过tty_driver::tty_operations::install或者tty_standard_install为tty设备安装入口 */
          tty_ldisc_setup
          /* 打开线路规程 */
            tty_ldisc_open
            /* 调用tty_ldisc::tty_ldisc_ops::open, 对于N_TTY为n_tty_open */
      tty_add_file
      /* 关联文件到tty_struce */
      tty_struct::tty_operations::open
      /* 同tty_driver::tty_operations::open, 对于串口即uart_open */

    uar_open分析如下

    uart_open 
      tty_port_open
        uart_port_activate
        /* 即tty_port::tty_port_operations::activate */
          uart_startup
            uart_port_startup
              uart_change_pm
              /* 调用uart_port::uart_ops::pm */
              get_zeroed_page
              /* 分配一页并分配给uart_state.xmit.buf */
              uart_circ_clear
              /* 初始化TX环形缓冲区头和尾指针 */ 
              uart_port::uart_ops::startup
              uart_change_speed

    4. 写入

    write会调用tty_write, 其分析如下:

    tty_write
      file_tty
      /* 通过file::tty_file_private::tty_struct获取对应的tty_struct */
      do_tty_write
      /* 调用tty_struct::tty_ldisc::tty_ldisc_ops::write */
        n_tty_write
        /* 对于类型N_TTY的线路规程, write为n_tty_write */
          process_echoes
          /* 处理所有待处理的echoed字符 */
            __process_echoes
            /* 写入待处理的echo字符 */
              tty_write_room
              /* 调用tty_struct::tty_operations::write_room */
              echo_buf
              tty_put_char
              /* 
               * 调用tty_struct::tty_operations::put_char
               * 或调用tty_struct::tty_operations::write
               */
              do_output_char
              /* 调用tty_struct::tty_operations::write */
            tty_struct::tty_operations::flush_chars
            /* 对于uart为uart_flush_buffer */
          process_output_block
          process_output
          tty_struct::tty_operations::flush_chars
          tty_struct::tty_operations::write
    /* 对于uart为uart_write */

    uart_write分析如下

    uart_write
      uart_state::circ_buf
      /* 获取环形缓冲区 */
      memcpy
      /* 将待写数据拷贝至环形缓冲区 */
      __uart_start
      uart_port::uart_ops::wake_peer
      uart_port::uart_ops::start_tx

    5. 读取

    read会调用tty_read, 其分析如下:

    tty_read
      tty_struct::tty_ldisc::tty_ldisc_ops::read
      /* 对于类型N_TTY的线路规程, 为n_tty_read */
        n_tty_read
          tty_buffer_flush_work
            flush_work
              flush_to_ldisc
              /* 将数据从tty缓冲区刷新到线路规程 */
                receive_buf
                  tty_ldisc_receive_buf
                  /* 调用tty_struct::tty_ldisc::tty_ldisc_ops::receive_buf2 */
                    n_tty_receive_buf2
                      n_tty_receive_buf_common
                        __receive_buf
                          n_tty_receive_buf_real_raw
          canon_copy_from_read_buf
          /* ICANON ON */
          copy_from_read_buf
          /* ICANON OFF */
            copy_to_user
            /* 将数据拷贝至用户空间 */
  • 相关阅读:
    linux下git以及github的连接与使用
    在windows上如何安装python web引擎jinja2
    JS请求服务器并使页面跳转(转)
    Spring MVC中Session的正确用法<转>
    Eclipse上安装GIT插件EGit及使用
    深入理解JavaScript事件循环机制
    React Hooks useContext 进行父子组件传值
    Remove all your local git branches but keep master
    常见的web前端性能优化
    js知识梳理2:对象属性的操作
  • 原文地址:https://www.cnblogs.com/hzl6255/p/9551673.html
Copyright © 2011-2022 走看看