打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
linux0.11使用open()函数打开一个文件(普通文件或/dev目录下的设备文件)后,对其调
1.         /dev/tty0终端设备是键盘与显示器的组合吗?它是如何操作的?当使用open()函数打开一个文件(普通文件或/dev目录下的设备文件)后,对其调用read()/write()进行读/写操作,为什么就能够正确的使用相应的设备驱动程序进行读写?
(1)    答:/dev/tty0中断设备是键盘与显示器的组合。当对它进行读操作时,它是读取键盘输入,当对它进行写操作时,它是对显示器进行写操作。
(2)    linux只包含字符设备和块设备这两种设备,为了了解整个工作过程,需要对其执行过程进行分析。
(3)    open()函数首先为打开文件分配文件句柄fd,然后再为打开的文件在文件表中分配一个空闲文件结构项,然后让刚分配的文件句柄fd的文件结构指针指向搜索到的文件结构,然后调用namei()取得对应文件i节点,然后让文件结构与这个i节点结构相关联。i节点中包含有该文件所代表的主设备号和子设备号,还有它属于什么类型文件(如普通文件、目录文件、字符设备文件、块设备文件、管道文件等)。
(4)    read()/write()根据open()返回的文件句柄fd,取得该文件的i节点。根据该i节点的属性字段(i_pipe和i_mode)来决定调用相应的读写操作函数。若是管道则调用read_pipe()/write_pipe(),若是字符型设备则调用rw_char(),若是块设备则调用block_read()/block_write(),若是普通文件则调用file_read()/file_write()。注:linux的目录文件只能用read()读,不能用write()写,目录文件只能通过专用函数进行写操作。
a.   block_read()/block_write()首先由设备文件中位置pos换算成开始读写盘块的块序号block,并求出需读写的第一个字节在该设备块中的偏移位置offset。若是读操作则内核调用breada()进行读取。若是写操作,那么对于内核来说,写操作是向高速缓冲区中写如数据,什么时候数据写入设备是由高速缓冲管理程序决定并处理的。另外,因为块设备是以块为单位进行读写的,因此,对于写开始位置不处于块起始位置时,需要先将开始字节所在的整个块读出,然后将需要的数据从写开始处填写满该块,在将完整的一块数据写盘(即交由高速缓冲程序处理)。因此,当要正好写入一块数据时,则调用getblk()直接申请一块高速缓冲块,并将用户数据放入即可。否则需要调用breada()读入将被写入部分数据的数据块,然后再进行写操作。最后返回读出或写入的字节数。
breada()首先调用getblk()取得一个缓冲块,然后调用ll_rw_block()读取该块数据,最后返回该块缓冲区指针。
ll_rw_block()主要功能是创建块设备读写请求项,并插入到对应块设备读写请求队列中(由i节点的主设备号决定)。如果当前请求项是该队列第一项,则立刻执行相应设备的请求函数,否则利用电梯算法插入到该队列中的合适位置。实际的读写操作是由设备的request_fn()函数来完成该设备队列的读/写请求操作。对于虚拟盘操作,该函数是do_rd_request()。对于硬盘操作,该函数是do_fd_request()。对于软盘操作,该函数是do_fd_request()。
do_rd_request()虚拟盘读/写请求项操作函数。它首先计算请求项中指定的起始扇区对应虚拟盘所处内存起始位置addr和要求扇区数对应字节长度len,然后根据请求项中命令进行操作。若是写命令WRITE,就把请求项所指缓冲区中的数据直接复制到内存位置addr处。若是读操作反之。数据复制完成后对本次请求项作一些结束处理,然后跳转到函数开始处再去处理下一个请求项,若已没有请求项则退出。
do_hd_request()硬盘读/写请求项操作函数。该函数根据设备当前请求项中的设备号和起始扇区号信息首先计算得到对应硬盘上的柱面号,当前扇区中的扇区号,磁头号等信息。然后根据请求项中的命令(READ/WRITE)调用hd_out()向硬盘发送相应的读写操作命令,并设置硬盘中断处理程序hd_interrupt中应调用的函数read_intr()/write_intr()。do_hd_request()返回,若是读操作则返回到breada()中进程睡眠并等待读操作完成(写操作是由缓冲区管理程序执行的)。当硬盘中断产生时执行hd_interrupt()函数(hd_interrupt()硬盘中断处理程序是在内核初始化时调用hd_init()时设定的)。它首先保存当前运行环境,并将ds、es设置为内核数据段,代码段cs已在中断产生时被中断门设置为内核代码段了,这样就进入了内核状态,具有内核特权级。然后调用在do_out()中设定的读/写函数read_intr()/write_intr()来处理硬盘读写完后的剩余工作(包括叫醒睡眠在当前状态的进程等)。然后再调用do_hd_request()处理下一个请求。当从do_hd_request()返回后就恢复中断时保存的环境,并退出中断继续执行,等待下一个硬盘中断请求。
do_fd_request()软盘读写请求项处理函数。它与硬盘读写操作过程类似。
b.  file_read()/file_write()与block_read()/block_write()相似,都是调用bread()或breada()去读取指定设备的指定数据块。区别在于file_read()/file_write()是通过i节点获取设备号,由文件结构获得读写指针位置,按照文件系统结构计算出设备上块号和相对偏移位置来调用bread()。而block_read()/block_write()是通过设备文件中位置pos换算成开始读写盘块的块序号block,并求出需读写的第一个字节在该设备块中的偏移位置offset调用bread()进行操作的。
rw_char()字符设备读写操作函数。根据主设备号调用对应设备的读写操作函数。/dev/mem对应内存读写操作函数rw_memory()。/dev/tty对应终端读写操作函数rw_tty()。/dev/ttyx对应串口终端的读写操作函数rw_ttyx()。
rw_memory()内存读写操作函数尚未完全实现。
rw_tty()终端读写操作函数。它调用rw_ttyx()。
rw_ttyx()  tty中断读写操作函数,根据读/写命令调用tty_read()/tty_write()进行操作。每个tty设备都有3个缓冲队列,分别是读缓冲队列read_q,写缓冲队列write_q,辅助缓冲队列secondary。
tty_read()用于从终端辅助缓冲队列secondary中读取指定数量的字符放到用户指定的缓冲区中。具体读取哪个tty设备的读缓冲队列,则由子设备号决定。当读取的是控制台终端辅助缓冲队列secondary中数据时,该队列中数据是由键盘输入的,并由键盘中断处理程序keyboard_interrupt读入,将对应字符放入读字符缓冲队列read_q中,并调用函数do_tty_interrupt()(实际上是调用copy_to_cooked())将读缓冲队列read_q中的字符转换为规范模式后放入辅助队列secondary中,如果回显标志ECHO置位,则copy_to_cooked()会将该字符放入该tty写缓冲队列write_q中,并调用该tty的写操作函数,对于控制台终端是con_write()。当读取的是串口终端辅助缓冲队列secondary中数据时,该对列中数据是由串口终端处理程序rs1_interrupt/rs2_interrupt读入并将接收到的字符放入读缓冲队列read_q中,并调用函数do_tty_interrupt()(实际上是调用copy_to_cooked())将读缓冲队列read_q中的字符转换为规范模式后放入辅助队列secondary中,如果回显标志ECHO置位,则copy_to_cooked()会将该字符放入该tty写缓冲队列write_q中,并调用该tty的写操作函数,对于串口终端是rs_write()。
tty_write()用于将用户缓冲区的字符写入对应的tty写队列缓冲区write_q中。最后调用相应的tty写函数,把写队列缓冲区write_q中的字符显示在控制台屏幕上或通过串行端口发送出去。如果当前处理的tty是控制终端,那么调用的是con_write()函数,如果当前处理的tty是串行端口,则调用的是rs_write()函数,由子设备号决定当前是哪个tty设备。
con_write()控制台写函数,从终端对应的tty写缓冲区队列中取字符,针对每一个字符进行分析,若是控制字符或转义字符或控制序列,则进行光标定位、字符删除等控制处理。对于普通字符就直接在光标处显示。
rs_write()串行数据发送输出函数,该函数实际上开启发送保持寄存器已空标志,此后当发送保持寄存器空时,UART就会产生中断请求,在该中断处理过程中,会将写队列字符输出到发送保持寄存器中,一旦UART将该字符发送出去,发送保持寄存器又会变空而引发中断请求,这样重复处理就会将写队列中字符一个一个的发送出去。当写队列中所有字符都发送出去,中断处理程序就会把中断允许寄存器中发送保持寄存器中断允许标志复位掉,从而再次禁止发送保持寄存器空引发中断请求。此次“循环”发送操作也随之结束。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
LINUX0.11内核阅读笔记
字符设备
Linux PPPoE
TTY的那些事儿
LINUX 内核源文件介绍以及头文件介绍
tty0代表的是什么设备?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服