Linux源码阅读笔记14-IO体系结构与访问设备

简介: Linux源码阅读笔记14-IO体系结构与访问设备

IO体系结构

与外设通信通常称为输入输出,一般缩写为I/O。在实现外设IO的时候,内核必须处理三个可能出现的问题:

  • 必须根据具体的设备类型和模型,使用各种方法对硬件寻址。
  • 内核必须向用户应用程序和系统工具提供访问各种设备的方法。但凡有可能,都应当采用统一的方案,确保程序设计的工作量不会过多,同时保证应用程序能够在不考虑特定硬件方法的情况下进行互操作。
  • 用户空间需要知道内核中有哪些设备可用。

硬件设备可以以多种方式连接到主板上,主板上的扩展槽或者外部连接器最常见的方法;当然扩展硬件也可以直接集成到主板上。

系统总线

尽管外设的范围看上去是无线的,但是他们不直接连接到CPU,而是通过总线连接起来。总线负责设备与CPU之间及各个设备之间的通信。有代表性的总线有:

  • PCI(Peripheral Component Interconnect)
  • ISA(Industrial Standard Architecuture)
  • SBus
  • IEEE 1394
  • SCSI(Small Computer System Interface)
  • USB(Universal Serial Bus)
  • 并口与串口(Parallel and Sreial Interface)

与外设交互

与外设通信方法,有几种方法可以与连接到系统的硬件通信

  • IO端口:使用IA-32和很多其他体系结构都有IO端口,在这种情况下,内核发送数据给IO控制器。数据的目标设备通过唯一的端口号标识,数据被传输到设备进行处理。处理器管理一个独立的虚拟地址空间,可能用于管理所有IO地址。IO地址空间不关联到普通的系统内核。因为端口也可以映射到内存中,这样会引起混淆。在IA-32体系结构上,端口地址空间由2的16次方个不同的8位地址组成,通过0x0到0xFFFF之间的数字唯一标识。
  • IO内存映射:程序员必须寻址很多设备,与内存的处理方式类似。因此现在处理器提供对IO端口进行内存地址映射,将特殊外设的端口地址映射到普通内存中。
  • 轮询和中断: 轮询(polling)策略比较健达,只需要重复询问设备数据是否可用,如果可以则处理器取回数据;中断策略比较好,每个CPU都提供中断线,可由各个系统设备共享,每个中断通过唯一号码识别,内核对使用每个中断提供一个服务例程。

通过总线控制设备

并非所有设备都是直接通过I/O语句寻址,也有通过总线系统访问的。具体的方式与所使用的总线和设备相关。并非所有设备类别都可以连接到所有总线系统。(比如:将硬盘和CD记录机连接到SCSI接口,但图形卡就行)。

访问设备

设备特殊文件(设备文件)用于访问扩展设备。这些文件并不关联到硬盘或其他任何存储介质上的数据段,而是建立了与某个设备驱动程勋的连接,以支持与扩展设备的通信。

  • 就应用程序而言,普通文件和设备文件的处理有一定差别。二者都是可以通过同样的库函数处理。
  • /dev目录下的一些成员,特别在访问权限上,访问之前的字母是b或c,分别代表块设备和字符设备;设备文件没有文件长度,而是增加另外两个值,分别是主设备号和次设备号。
  • /dev/hda,/dev/hdb,/dev/sda,/dev/sdb:hda(一般是IDE接口的硬盘,sda一般是指sata接口的硬盘)。
  • 热插拔消息:每当内核检测到一个设备时,都会创建一个内核对象kobject。该对象借助于sysfs文件系统导出用户到用户层,内核还像用户空间发送一条热插拔消息。
  • 网卡和其他设备:字符设备和块设备不是内核管理的全部设备类别。网卡在内核重具有特殊地位,它无法融入到分类方案当中,事实很明显:网卡没有设备文件。相反,用户程序必须使用套接字与网卡通信。套接字是一个抽象层,对所有网卡提供抽象视图。标准库的网络相关函数调用socketcall系统调用与内核通信交互。进而访问网卡。

字符设备、块设备和其他设备

根据外设与系统之间交换数据的方法,可以将设备分为几种类别。有些设备非常适合于面向字符的数据交换,因为数据传输量很低。其他的设备则更适合于处理包含固定数目字节 的数据块。内核会区分字符设备和块设备。

字符设备与块设备
  • 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取,相反,此类设备支持按字节/字符读取。比如:调度解调器就是典型的字符设备。
  • 块设备:应用可以随机访问设备数据,程序自行确定数据的位置。比如:硬盘就是块设备,应用程序可以寻址磁盘上的任何位置,并由此读取数据。
设备驱动程序

用于系统连接的输入/输出装置通信,如硬盘,软驱,各种接口、声卡等。设备驱动程序的任务在于支持应用程序由设备文件与设备通讯,是的能够按照适当方式在设备上读取/写入数据。

设备号

设备号,就是系统分配一个编号,设备号是一个无符号32位整数,包括主设备号+次设备号,主设备号位高12位,次设备号位低20位。

设备文件需要设备号才能创建,设备驱动也需要设备号才能装载,设备文件是通过主设备号找到它的驱动;设备驱动利用次设备号才知道他要操作的是具体哪个设备。

设备文件查询
  • 标识设备文件查询
ls -l /dev
  • 查询/dev目录中与sda硬盘相关的其他设备文件:
ls -l /dev/sda*
动态创建设备文件

/dev中的设备结点一般是在基于磁盘的文件系统中静态创建的。随着支持设备越来越多,必须安置和管理越来越多的项,典型发布版大约包含20000项。几乎所有的发布版都将 /dev内容的管理工作切换到udevd,这是一个守护进程,允许从用户层动态创建设备文件。 udevd基本思想,即使从用户层管理设备文件,内核的支持也是对必须的,否则就 无法判断系统上有哪些设备可用。

字符设备

相关文章
|
1月前
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
89 0
|
3月前
|
域名解析 网络协议 安全
在Linux中,想在命令行下访问某个网站,并且该网站域名还没有解析,如何做?
在Linux中,想在命令行下访问某个网站,并且该网站域名还没有解析,如何做?
|
1月前
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
82 1
Linux C/C++之IO多路复用(aio)
|
1月前
|
Ubuntu Linux Python
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
在Linux系统中,使用Tkinter库时可能会遇到中文显示乱码的问题,这通常是由于字体支持问题导致的,可以通过更换支持中文的字体来解决。
125 0
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
|
3月前
|
缓存 安全 Linux
Linux 五种IO模型
Linux 五种IO模型
|
1月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
83 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
1月前
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
24 0
Linux C/C++之IO多路复用(poll,epoll)
|
3月前
|
Linux 调度 芯片
Linux0.11 内核体系结构(八)(下)
Linux0.11 内核体系结构(八)
58 1
|
3月前
|
JavaScript Linux 应用服务中间件
【Azure 应用服务】FTP 部署 Vue 生成的静态文件至 Linux App Service 后,访问App Service URL依旧显示Azure默认页面问题
【Azure 应用服务】FTP 部署 Vue 生成的静态文件至 Linux App Service 后,访问App Service URL依旧显示Azure默认页面问题
|
3月前
|
机器学习/深度学习 Ubuntu Linux
在Linux中,如何按照该要求抓包:只过滤出访问http服务的,目标ip为192.168.0.111,一共抓1000个包,并且保存到1.cap文件中?
在Linux中,如何按照该要求抓包:只过滤出访问http服务的,目标ip为192.168.0.111,一共抓1000个包,并且保存到1.cap文件中?