【VC++开源代码栏目提醒】:网学会员为广大网友收集整理了,【精品】Linux tty core 源码分析 - 其它资料,希望对大家有所帮助!
Linux tty core 源码分析 日期:2011-02-08 来源:CSDN 作者:sirzjp本文以 linux 2.6.27 内核为基础,阅读 tty core 源码并作注解,自己接触时间不长,希望与爱好者共同分享,错误之处还望指正。
linux tty core 是建立在字符设备驱动的基础之上,并为 tty 类型设备(串口、控制台、虚拟终端)提供一个公用的平台。
所以任何一个 tty 设备驱动的注册都是作为一个字符设备驱动而操作的。
下面我们看看
代码中是如何处理的:/ 3/2004 jmc: why do these devices exist ///tty 核心默认在内核中实现的字符型 tty 设备驱动static struct cdev tty_cdev console_cdevifdef CONFIG_UNIX98_PTYSstatic struct cdev ptmx_cdevendififdef CONFIG_VTstatic struct cdev
vc0_cdevendif/ Ok now we can initialize the rest of the tty devices and can count on memory allocations interrupts etc../static int __init tty_initvoid//在字符设备模型中加入注册 tty_cdev 驱动并加入/dev/tty 这样的设备cdev_initamptty_cdev amptty_fopsif cdev_addamptty_cdev MKDEVTTYAUX_MAJOR 0 1 register_chrdev_regionMKDEVTTYAUX_MAJOR 0 1 quot/dev/ttyquot lt 0 panicquotCouldnt register /dev/tty drivernquotdevice_create_drvdatatty_class NULL MKDEVTTYAUX_MAJOR 0 NULL quotttyquot//在字符设备模型中加入注册 console_cdev 驱动并加入/dev/console 这样的设备cdev_initampconsole_cdev ampconsole_fopsif cdev_addampconsole_cdev MKDEVTTYAUX_MAJOR 1 1 register_chrdev_regionMKDEVTTYAUX_MAJOR 1 1 quot/dev/consolequot lt 0 panicquotCouldnt register /dev/console drivernquotdevice_create_drvdatatty_class NULL MKDEVTTYAUX_MAJOR 1 NULL quotconsolequot//在字符设备模型中加入注册 ptmx_cdev 驱动并加入/dev/ptmx 这样的设备ifdef CONFIG_UNIX98_PTYScdev_initampptmx_cdev ampptmx_fopsif cdev_addampptmx_cdev MKDEVTTYAUX_MAJOR 2 1 register_chrdev_regionMKDEVTTYAUX_MAJOR 2 1 quot/dev/ptmxquot lt 0 panicquotCouldnt register /dev/ptmx drivernquotdevice_create_drvdatatty_class NULL MKDEVTTYAUX_MAJOR 2 NULL quotptmxquotendif//在字符设备模型中加入注册
vc0_cdev 驱动并加入/dev/tty0 这样的设备ifdef CONFIG_VTcdev_initampvc0_cdev ampconsole_fopsif cdev_addampvc0_cdev MKDEVTTY_MAJOR 0 1 register_chrdev_regionMKDEVTTY_MAJOR 0 1 quot/dev/
vc/0quot lt 0 panicquotCouldnt register /dev/tty0 drivernquotdevice_create_drvdatatty_class NULL MKDEVTTY_MAJOR 0 NULL quottty0quotvty_init //这里暂时不做解释endifreturn 0//上面是本身加入的,也就是我们系统一般都有的设备,而且这几种设备都是指向其他的设备,在 tty_open 中我们将看到以后都会指向其//他具体的设备。
对这几种设备大多数人都存在一定的混淆,这里我就自己的理解解释下:// /dev/console 51 表示系统的控制台// /dev/tty 50 表示进程的控制终端// /dev/tty0 40 表示当前使用的虚拟终端// 这样的解释也不是很清楚,这得从历史说起,以前计算机还是比较昂贵的时候,一台电脑上一般接有很多键盘与显示器的组合设备用以//操作计算机这样的组合设备就是所谓的终端,而还存在一种直接和电脑连接键盘和显示器这就是控制台。
而现在的应用环境发生了变化,//一般把能直接显示系统信息的终端称呼为系统控制台,而其他设备则称呼虚拟终端。
也就是当前虚拟终端作控制台。
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_fasyncifdef CONFIG_UNIX98_PTYSstatic const struct file_operations ptmx_fops .llseek no_llseek.read tty_read.write tty_write.poll tty_poll.unlocked_ioctl tty_ioctl.compat_ioctl tty_compat_ioctl.open ptmx_open.release tty_release.fasync tty_fasyncendifstatic 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//从上面看几个驱动的操作函数大致相同,只有 ptmx_fops 的 open 方法和 console_fops 的 write 方法不同其他操作都是相同的所以在其//他操作上要兼顾各种设备//下面我们介绍下 tty_driver 结构和 tty_struct 结构。
tty_driver 表示一个具体的 tty 设备的驱动程序,而 tty_struct 表示 tty 设备在//具体的分析中介绍其成员。
struct tty_driver int magic / magic number for this structure /struct kref kref / Reference management /struct cdev cdev//可见 tty 设备驱动是一个字符设备设备驱动struct module ownerconst char driver_name//这里是指驱动程序的名字const char name//tty 设备的命名相关int name_base / offset of printed name /int major / major device number /int minor_start / start of minor device number /int minor_num / number of possible devices /int num / number of devices allocated /short type / type of tty driver /short subtype / subtype of tty driver /struct ktermios init_termios / Initial termios /int 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//驱动操作的具体 tty 设备struct ktermios termiosstruct ktermios termios_lockedvoid driver_state/ Driver methods /const struct tty_operations opsstruct list_head tty_drivers //用于链接 tty 驱动全局链表//下面对 tty_open 函数进行分析,open 函数的具体操作就是初始化 tty_struct 结构并作为赋值 filp-gtprivate_data为后续的操作做准备/ tty_open - open a tty device inode: inode of device file filp: file pointer to tty tty_open and tty_release keep up the tty count that contains the number of opens done on a tty. We cannot use the inode-count as different inodes might point to the same tty. Open-counting is needed for pty masters as well as for keeping track of serial lines: DTR is dropped when the last close happens. This is not done solely through tty-gtcount now. - Ted 1/27/92 The termios state of a pty is reset on first open so that settings dont persist across reuse. Locking: tty_mutex protects tty get_tty_driver and init_dev work. tty-gtcount should protect the rest. -gtsiglock protects -gtsignal/-gtsighand/static int __tty_openstruct inode inode struct file filpstruct tty_struct ttyint noctty retvalstruct tty_driver driverint indexdev_t device inode-gti_rdev//得到设备的设备号unsigned short saved_flags filp-gtf_flagsnonseekable_openinode filp//主要是设置 file-gtf_mode 的一些标志使文件不可定位retry_open:noctty filp-gtf_flags amp O_NOCTTY;//是否终端绑定到指定的进程index -1retval 0mutex_lockamptty_mutex//这里表示的是设备号为(50)及/dev/tty 是进程控制终端的别名,因此是一个要找到真正的设备if device MKDEVTTYAUX_MAJOR 0 tty get_current_tty if tty //进程没有控制终端则直接返回 mutex_unlockamptty_mutex return -ENXIO driver tty-gtdriver index tty-gtindex//设备在驱动中的 driver-gtttys 中的位置 filp-gtf_flags O_NONBLOCK / Dont let /dev/tty block / / noctty 1 / goto got_driverifdef CONFIG_VT//这里表示的是设备号为(40)及/dev/tty0 是当前进程使用虚拟终端的别名,因此是一个要找到真正的设备if device MKDEVTTY_MAJOR 0 extern struct tty_driver console_driver//控制台的驱动 driver console_driver index fg_console//表示当前控制台索引 noctty 1 goto got_driverendif//这里表示的是设备号为(51)及/dev/console 是指系统控制台,因此是一个要找到真正的设备if device MKDEVTTYAUX_MAJOR 1 driver console_deviceampindex if driver / Dont let /dev/console block / filp-gtf_flags O_NONBLOCK noctty 1 goto got_driver mutex_unlockamptty_mutex return -ENODEV//依据设备的设备号来确定设备在具体驱动中的索引。
driver get_tty_driverdevice ampindexif driver mutex_unlockamptty_mutex return -ENODEV/到此位置我们的目的是确定设备驱动和设备在驱动中的位置以及设备是否和进程绑定/got_driver://init_dev 初始化一个 tty_struct 结构 具体在下面分析retval init_devdriver index ampttymutex_unlockamptty_mutexif retval return retvalfilp-gtprivate_data tty//把 tty_struct 结构作为 file-gtprivate_data 这也是 open 函数的主要目的file_movefilp amptty-gttty_filescheck_tty_counttty quottty_openquot//统计 tty 设备打开的次数if tty-gtdriver-gttype TTY_DRIVER_TYPE_PTY ampamp tty-gtdriver-gtsubtype PTY_TYPE_MASTER noctty 1ifdef TTY_DEBUG_HANGUPprintkKERN_DEBUG quotopening s...quot tty-gtnameendifif retval if tty-gtops-gtopen retval tty-gtops-gtopentty filp//调用 tty_operations 中的回调函数 tty 驱动中我们要实现的 else retval -ENODEVfilp-gtf_flags saved_flagsif retval ampamp test_bitTTY_EXCLUSIVE amptty-gtflags ampamp //设备是否为互斥设备 capableCAP_SYS_ADMIN retval -EBUSYif retval ifdef TTY_DEBUG_HANGUP printkKERN_DEBUG quoterror d in opening s...quot retval tty-gtnameendif release_devfilp//init_dev 的反操作 if retval -ERESTARTSYS return retval if signal_pendingcurrent return retval schedule / Need to reset f_op in case a hangup happened. / if filp-gtf_op amphung_up_tty_fops filp-gtf_op amptty_fops goto retry_openmutex_lockamptty_mutexspin_lock_irqampcurrent-gtsighand-gtsiglockif noctty ampamp //设备和进程绑定作为进程回话的控制终端 current-gtsignal-gtleader ampamp current-gtsignal-gttty ampamp tty-gtsession NULL __proc_set_ttycurrent ttyspin_unlock_irqampcurrent-gtsighand-gtsiglockmutex_unlockamptty_mutexreturn 0/ BKL pushdown: scary code avoidance wrapper /static int tty_openstruct inode inode struct file filpint retlock_kernelret __tty_openinode filpunlock_kernelreturn ret/ init_dev - initialise a tty device driver: tty driver we are opening a device on idx: device index tty: returned tty structure Prepare a tty device. This may not be a quotnewquot clean device but could also be an active device. The pty drivers require special handling because of this. Locking: The function is called under the tty_mutex which protects us from the tty struct or driver itself going away. On exit the tty device has the line discipline attached and a reference count of 1. If a pair was created for pty/tty use and the other was a pty master then it too has a reference count of 1. WSH 06/09/97: Rewritten to remove races and properly clean up after a failed open. The new code protects the open with a mutex so its really quite straightforward. The mutex locking can probably be relaxed for the most common case of reopening a tty./static int init_devstruct tty_driver driver int idxstruct tty_struct ret_ttystruct tty_struct tty o_ttystruct ktermios tp tp_loc o_tp o_tp_locstruct ktermios ltp ltp_loc o_ltp o_ltp_locint retval 0/ check whether were reopening an existing tty /if driver-gtflags amp TTY_DRIVER_DEVPTS_MEM //伪终端初始化,从设备。
tty devpts_get_ttyidx / If we dont have a tty here on a slave open its because the master already started the close process and theres no relation between devpts file and tty anymore. / if tty ampamp driver-gtsubtype PTY_TYPE_SLAVE retval -EIO goto end_init / Its safe from now on because init_dev is called with tty_mutex held and release_dev wont change tty-gtcount or tty-gtflags without having to grab tty_mutex / if tty ampamp driver-gtsubtype PTY_TYPE_MASTER tty tty-gtlink else tty driver-gtttysidxif tty goto fast_track//fast_track 表示设备不是第一次打开/ First time open is complex especially for PTY devices. This code guarantees that either everything succeeds and the TTY is ready for operation or else the table slots are vacated and the allocated memory released. Except that the termios and locked termios may be retained. /if try_module_getdriver-gtowner retval -ENODEV goto end_inito_tty NULLtp o_tp NULLltp o_ltp NULLtty alloc_tty_structif tty goto fail_no_meminitialize_tty_structttytty-gtdriver drivertty-gtops driver-gtopstty-gtindex idxtty_line_namedriver idx tty-gtnameif driver-gtflags amp TTY_DRIVER_DEVPTS_MEM tp_loc amptty-gttermios ltp_loc amptty-gttermios_locked else tp_loc ampdriver-gttermiosidx ltp_loc ampdriver-gttermios_lockedidxif tp_loc tp kmallocsizeofstruct ktermios GFP_KERNEL if tp goto free_mem_out tp driver-gtinit_termiosif ltp_loc ltp kzallocsizeofstruct ktermios GFP_KERNEL if ltp goto free_mem_outif driver-gttype TTY_DRIVER_TYPE_PTY o_tty alloc_tty_struct if o_tty goto free_mem_out initialize_tty_structo_tty o_tty-gtdriver driver-gtother o_tty-gtops driver-gtops o_tty-gtindex idx tty_line_namedriver-gtother idx o_tty-gtname if driver-gtflags amp TTY_DRIVER_DEVPTS_MEM o_tp_loc ampo_tty-gttermios o_ltp_loc ampo_tty-gttermios_locked else o_tp_loc ampdriver-gtother-gttermiosidx o_ltp_loc ampdriver-gtother-gttermios_lockedidx if o_tp_loc o_tp kmallocsizeofstruct ktermios GFP_KERNEL if o_tp goto free_mem_out o_tp driver-gtother-gtinit_termios if o_ltp_loc o_ltp kzallocsizeofstruct ktermios GFP_KERNEL if o_ltp goto free_mem_out / Everything allocated ... set up the o_tty structure. / if driver-gtother-gtflags amp TTY_DRIVER_DEVPTS_MEM driver-gtother-gtttysidx o_tty if o_tp_loc o_tp_loc o_tp if o_ltp_loc o_ltp_loc o_ltp o_tty-gttermios o_tp_loc o_tty-gttermios_locked o_ltp_locdriver-gtother-gtrefcount if driver-gtsubtype PTY_TYPE_MASTER o_tty-gtcount / Establish the links in both directions / tty-gtlink o_tty o_tty-gtlink tty/ All structures have been allocated so now we install them. Failures after this point use release_tty to clean up so theres no need to null out the local pointers. /if driver-gtflags amp TTY_DRIVER_DEVPTS_MEM driver-gtttysidx ttyif tp_loc tp_loc tpif ltp_loc ltp_loc ltptty-gttermios tp_loctty-gttermios_locked ltp_loc/ Compatibility until drivers always set this /tty-gttermios-gtc_ispeed tty_termios_input_baud_ratetty-gttermiostty-gttermios-gtc_ospeed tty_termios_baud_ratetty-gttermiosdriver-gtrefcounttty-gtcount/ Structures all installed ... call the ldisc open routines. If we fail here just call release_tty to clean up. No need to decrement the use counts as release_tty doesnt care. /retval tty_ldisc_setuptty o_tty//打开线路规程if retval goto release_mem_out goto success/ This fast open can be used if the tty is already open. No memory is allocated and the only failures are from attempting to open a closing tty or attempting multiple opens on a pty master. /fast_track:if test_bitTTY_CLOSING amptty-gtflags retval -EIO goto end_initif driver-gttype TTY_DRIVER_TYPE_PTY ampamp driver-gtsubtype PTY_TYPE_MASTER / special case for PTY masters: only one open permitted and the slave side open count is incremented as well. / if tty-gtcount retval -EIO goto end_init tty-gtlink-gtcounttty-gtcounttty-gtdriver driver / N.B. why do this every time // FIXME /if test_bitTTY_LDISC amptty-gtflags printkKERN_ERR quotinit_dev but no ldiscnquotsuccess:ret_tty tty/ All paths come through here to release the mutex /end_init:return retval/ Release locally allo.
上一篇:
一个U盘病毒汇编源码分析
下一篇:
竞赛中运动员的心理障碍与心理训练分析