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, , 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] = ;
toptions.c_cc[VTIME] = ; tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSANOW, &toptions); uint8_t data[] = { 0x01, 0x09, 0x10, 0x00 };
write(fd, data, ); memset(read_data, , );
read(fd, data, ); return ;
}

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 TTY函数跟踪的更多相关文章

  1. Linux TTY驱动--Serial Core层【转】

    转自:http://blog.csdn.net/sharecode/article/details/9197567 版权声明:本文为博主原创文章,未经博主允许不得转载. 接上一节: Linux TTY ...

  2. linux select函数详解

    linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...

  3. 20135239 益西拉姆 linux内核分析 跟踪分析Linux内核的启动过程

    回顾 1.中断上下文的切换——保存现场&恢复现场 本节主要课程内容 Linux内核源代码简介 1.打开内核源代码页面 arch/目录:支持不同CPU的源代码:其中的X86是重点 init/目录 ...

  4. 动态替换Linux核心函数的原理和实现

    转载:https://www.ibm.com/developerworks/cn/linux/l-knldebug/ 动态替换Linux核心函数的原理和实现 在调试Linux核心模块时,有时需要能够实 ...

  5. Linux TTY介绍

    1. TTY介绍 TTY(TeleType)指Linux中的一类终端(Terminal)设备, 是一种字符设备 在Linux中, tty可分为如下几类- 串行端口终端(serial port term ...

  6. Linux Clone函数

    Linux Clone函数 之前某一次有过一次面试,问了内核中是怎么创建命名空间的? 下面就来扒一扒clone的精髓,以及如何通过它创建命名空间. 目录 Linux Clone函数 使用clone创建 ...

  7. Xdebug文档(四)函数跟踪

    Xdebug能让你把所有函数调用,包括参数和返回值以不同的格式记录到文件中. 这些号称“函数跟踪”功能能帮助你面对一个新应用程序,亦或者在程序运行时你想弄清楚它在做什么.函数跟踪功能可以选择性地显示函 ...

  8. Linux open函数

    Linux open函数 open 函数用于打开和创建文件.以下是 open 函数的简单描述 #include <fcntl.h> int open(const char *pathnam ...

  9. Linux TTY框架【转】

    本文转载自:http://ju.outofmemory.cn/entry/281168 1. 前言 由于串口的缘故,TTY是Linux系统中最普遍的一类设备,稍微了解Linux系统的同学,对它都不陌生 ...

随机推荐

  1. 【Maven学习】Eclipse使用maven问题集

    环境 jdk 1.8 eclipse 4.7 apache-maven-3.6.1 一.eclipse 编译maven工程步骤 1.Update Project 2.maven clean 3.mav ...

  2. laravel操作mongo详细说明

    原文地址:http://returnc.com/detail/3728   一个Eloquent模型和Query构建器,支持MongoDB,使用原始的Laravel API.该库扩展了原始的Larav ...

  3. Python 的语言特性

    谈谈对 Python 和其他语言的区别 Python 是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第三方库,他是一门强类型的可移植.可扩展,可嵌入的解释型编程语言,属于动态语言. ...

  4. 删除lvm时出现"Logical volume contains a filesystem in use"

    问题描述: k8s环境中需要重新创建lvm:/dev/mapper/test-vg-test-storage,该lvm挂载在/data/prometheus下面,在删除出现"Logical ...

  5. RobotFrameWork基本语法练习

    1.基本使用如下图 2.运行日志如下(可对照查看语句输出) Starting test: Test.Test Suite.test_case1 20180810 15:48:58.525 : INFO ...

  6. Angular 使用 ng2-file-upload 上传文件遇到的问题

    Angular 上传文件 可参考Angular2使用ng2-file-upload上传文件 这里记录在开发过程中遇到的问题: 删除选择的文件后,不能再选择上次选择的相同的文件 在 firefox 浏览 ...

  7. John Lemon's Haunted Jaunt(鬼屋游戏笔记)

    1.使用Unity  2019.2.3 2.角色移动的控制脚本 3.后期处理组件PostProcessLayer  (类似给相机加上了一层滤镜) 4.制作简单的怪物AI系统,使用 NAvMeshAge ...

  8. 「UR#6」懒癌

    「UR#6」懒癌 妈妈我居然看了六个小时题解,快救救乌干达的可怜儿童吧. 接下来开始膜官方题解: ​ 其实就算有上面两个结论也不是很好想到任意复杂度的做法,关键在于要想到一个人是怎么推断自己的狗是不是 ...

  9. EgretWing链接微信开发工具调试问题

    EgretWing链接微信开发工具调试问题 EgretWing 编译器支持持三种调试模式,Node.js .Chrome .EgretWing 扩展开发. 开发过程中会遇到工具配置错误. 这就需要在E ...

  10. 防止用户重复提交表单数据,session方式,js方式

    1. 使用session的方式创建Token令牌解决 创建一个生成令牌的工具类,在该类中有返回类的对象,生成token的方法 public class TokenUtil { /* *单例设计模式(保 ...