微信号:dellemc_tech

介绍:为戴尔易安信客户提供技术支持服务,为广大IT行业用户分享技术文章与行业信息。

Linux系统设备驱动入门

2016-07-06 17:22 EMC中文技术社区

本文介绍了Linux版本,内核模块及启动过程,设备驱动基础,以及动态配置磁盘设备的步骤。


 

Linux版本概述:


Linux是与Unix类似的操作系统,与传统操作系统和花费较高的Unix系统相比,它为个人电脑用户提供了一个免费或价格相对低廉的操作系统。Linux以快速高效著称,与其他服务器操作系统一样,它具有多重应用。


Linux厂商发行版本有 Red Hat, Debian, Fedora, Gentoo, SuSE, TurboLinux 等,其中一部分可以下载。


FTP发行商如:Sunsinte.org.uk, Sunsinte.unc.edu, www.isoimages.org

可通过以下URL找到Linux相关信息:

www. linux.com 和 www.linix.com

www.xfree86.com


Redhat企业版是一种常见的版本。它支持如Intel X86, Intel Itanium, AMD AMD64 and IBM z系列, POWER 系列, and S/390。Redhat使用最新版本稳定的2.5/2.6 Linux内核。

 

Redhat发展历程:

1991年,Linux内核发布。同年Bob Yong(加拿大人,多伦多大学毕业)在纽约UNIX用户组引入系统管理自由软件。

1993年,Bob Yang 建立了ACC公司,营销Linux和UNIX的支持软件和书籍杂志。

1994年,Marc Ewing(美国人,卡内基梅隆大学毕业)建立了自己的Linux分销业务,发布了Red Hat Linux 1.0。

1995年,Bob Yang 收购了Marc Ewing的业务,合并后的ACC公司成为新的Red Hat 软件公司,发布了Red Hat Linux 2.0。

1997年12月,Red Hat Linux 5.0发布,它支持Intel、alpha和Sparc平台和大多数的应用软件。极其简单易用的RPM模块化的安装、配置和卸载工具,使程序的安装可在15分钟内完成。软件升级也很方便,这对刚开始使用Linux的用户来说是一大福音。

2003年4月,Red Hat Linux 9.0发布。重点放在改善桌面应用方面,包括改进安装过程、更好的字体浏览、更好的打印服务等。统计表明,2003年,Red Hat的 Linux市场份额为86% 。

2004年4月30日,Red Hat公司正式停止对Red Hat 9.0版本的支持,标志著Red Hat Linux的正式完结。原本的桌面版Red Hat Linux发行包则与来自民间的Fedora计划合并,成为Fedora Core发行版本。Red Hat公司不再开发桌面版的Linux发行包,而将全部力量集中在服务器版的开发上,也就是Red Hat EnterpriseLinux版。 2005年10月RHEL4发布。

2007年3月,现行主流版本RHEL5发布(最新版本5.5)

2010年4月RHEL6 BETA测试版发布。

2011年04月12日 Oracle发布的Linux系统6.0(基于RedHat Enterprise Linux 6.0)

本文中,将采用Redhat企业版作为示例操作系统。

 


Linux内核模块及启动:


Linux内核采用模块化设计。系统启动时,只有最近贮存的内核会加载到内存中。此后,每当用户请求一个当前内核中不具备的功能,将动态加载一个内核模块(有时称为驱动)到内存中。


在安装过程中,对系统硬件进行探测。基于本次探测及用户提供的信息,安装程序决定在启动时加载哪一种模块。安装程序建立了动态加载机制以实现透明操作。


如果安装结束后新添加了硬件,并且该硬件需要一个内核模块,则系统必须为新硬件配置并加载合适的内核模块。



上图列出了BIOS(Basic Input and Output System)的启动过程。

不同类型的服务器使用了不同的引导装载程序。以上图例中,如果服务器是基于Intel的则引导装载程序可能是GRUB或LILO。如果是mainframe大型机则有可能使用IBM s390引导加载程序。

 

BIOS发起第一阶段主引导加载程序。BIOS将位于引导介质第一扇区中的程序加载入内存,我们称之为主引导记录(Master Boot Record或MBR)。主引导记录只有512字节大小,包含启动设备所需的机器代码,也称为引导加载程序(boot loader)。一旦BIOS将引导加载程序找到并将其加载入内存后,它就将启动程序的控制权交给二级引导加载程序。


在第一阶段,主引导加载程序通过BIOS从主引导记录被读入内存。它的主要工作是加载位于不同介质上任意位置的数据,通过这步操作来定位第二阶段引导加载程序。


第二阶段引导装载程序由第一阶段的引导装载程序发起,它包含有加载程序更需要磁盘空间的部分,如用户界面和内核引导程序。该阶段允许用户选择启动的操作系统或Linux内核。可用的两个启动加载程序是GRUB或LILO。GRUB是较新的启动加载程序,能够阅读ext2和ext3类型文件分区并在启动时加载它的配置文件——/boot/grub/grub.conf。LILO是较老的版本,它使用主引导记录中的信息以确定用户可用的启动选项。这意味着无论何时配置发生更改或内核被手动升级,必须通过命令来讲合适的信息写入MBR。命令为:/sbin/lilo -v -v。

 

GRUB 与 LILO 的比较

所有引导加载程序都以类似的方式工作,满足共同的目的。不过,LILO 和 GRUB 之间有很多不同之处:

  • LILO 没有交互式命令界面,而GRUB 拥有。

  • LILO 不支持网络引导,而GRUB 支持。

  • LILO 将关于可以引导的操作系统位置的信息物理上存储在MBR 中。如果修改了LILO 配置文件,必须将LILO第一阶段引导加载程序重写到MBR。相对于 GRUB,这是一个更为危险的选择,因为错误配置的MBR 可能会让系统无法引导。使用GRUB,如果配置文件配置错误,则只是默认转到GRUB 命令行界面。


接下来,系统将操作系统加载入内存并将设备的控制权转交给该操作系统。操作系统将会处理/etc/inittab文件,并依据/etc/inittab设定的内容,依序启动相关进程。首先启动的程序为/etc/rc.sysinit。rc.sysinit设置环境变量,启动置换空间,检查文件系统,并执行所有系统初始化所需的其他步骤。例如,绝大多数系统使用时钟,因此rc.sysinit读取/etc/sysconfig/clock配置文件以初始化硬件时钟。另一个例子是如果要初始化串口,rc.sysinit将会执行/etc/rc.serial文件。

 


Linux磁盘设备驱动基础:


Linux内核中采用可加载的模块化设计,常见的驱动程序是作为内核模块动态加载的。

 

模块的相关命令:

  • lsmod——列出当前系统加载的模块

  • rmmod——将当前模块卸载

  • insmod——加载当前模块

  • mknod——创建相关模块

 

Linux将设备看作文件,每个设备对应一个文件名,内核中对应一个索引节点,对文件操作的系统调用大都适用于设备文件。对某个具体设备而言,文件操作和设备驱动是同一事物的不同层次。Linux将设备分为两大类,一类是像磁盘那样的以块或扇区为单位、成块进行输入/输出的设备,称为块设备;另一类是像键盘那样以字符(字节)为单位,逐个字符进行输入/输出的设备,称为字符设备;文件系统通常建立在块设备上。


本文将以SCSI磁盘为例来介绍磁盘设备驱动的基础知识。

 

SCSI(小型计算机系统接口)总线是一种高效的点对点数据总线,它最多可以支持8个设备,其中包括多个主设备。在总线上的两个设备间数据可以以同步或异步方式,在32位数据宽度下传输率为40M字节来交换数据。SCSI总线上可以在设备间同时传输数据与状态信息。


Linux SCSI子系统由两个基本部分组成,每个由一个数据结构来表示。


Host

一个SCSI host即一个硬件设备:SCSI控制权。在Linux系统中可以存在相同类型的多个SCSI控制权,每个由一个单独的SCSI host来表示。这意味着一个SCSI设备驱动可以控制多个控制权实例。SCSI host总是SCSI命令的initiator设备。


Device

虽然SCSI支持多种类型设备如磁带机、CD-ROM等等,但最常见的SCSI设备是SCSI磁盘。SCSI设备总是SCSI命令的target。这些设备必须区别对待,例如象CD-ROM或者磁带机这种可移动设备,Linux必须检测介质是否已经移动。不同的磁盘类型有不同的主设备号,这样Linux可以将块设备请求发送到正确的SCSI设备。

 

SCSI子系统的初始化非常复杂,它必须反映出SCSI总线及其设备的动态性。Linux在启动时初始化SCSI子系统。 如果它找到一个SCSI控制器(即SCSI hosts)则会扫描此SCSI总线来找出总线上的所有设备。然后初始化这些设备并通过普通文件和buffer cache块设备操作使Linux内核的其它部分能使用这些设备。


一旦SCSI子系统初始化完成这些SCSI设备就可以使用了。每个活动的SCSI设备类型将其自身登记到内核以便Linux正确定向块设备请求。

 

如前所述,一个设备文件(即设备节点)可以通过mknod命令来创建,其中指定了主设备号和次设备号。主设备号表明某一类设备,一般对应着确定的驱动程序;次设备号一般是用于区分标明不同属性,例如不同的使用方法,不同的位置,不同的操作等,它标志着某个具体的物理设备。高字节为主设备号和底字节为次设备号。例如,在系统中的块设备SCSI 磁盘的主设备号是3,而多个SCSI 磁盘及其各个分区分别赋予次设备号1、2、3……

 

SCSI系统中磁盘设备驱动层级如下:sd——直接访问磁盘,sg——SCSI通用接口,sr——Data CD-ROMs,st——磁带。sg驱动是基于字符的设备而其他三个驱动都是块设备驱动。sg驱动主要用于扫描仪,刻录机,以及打印机。从第一个SCSI控制器开始,sg设备文件动态映射到SCSI总线上的SCSI IDs/LUNs。

块设备的本地文件名具有以下格式:/dev/sdln,l表示物理设备而n表示该物理设备上的分区号。当主机总线适配器发现附加连接的存储后Linux会在设备文件/dev/sd[l][n]中定义这些设备。当主机总线适配器监测到随机附带存储后Linux将会定义设备文件/dev/sd[l][n]。

 

按照以上定义,以文件/dev/sda1为例,物理设备是“a”而分区是“1”。Linux内核为SCSI设备保留了16个主设备编号,各主设备编号可拥有0-255个从设备编号。这些从设备编号包括SCSI设备的分区。对于每个磁盘设备Linux支持0到15个分区。其中,1至4为主分区,分区5以上为逻辑分区或扩展分区;以上限制只适用于Intel平台。默认情况下,Linux并不使用slice这一概念。因此,16个主设备编号和16个从设备编号意味着256个SCSI磁盘设备,内核能够扫描范围从1至255的磁盘设备。Red Hat Linux和SuSE SLES 7最大支持128个SCSI设备,而SuSE SLES 8版本支持256个SCSI设备。

 


动态设备配置步骤:


在Linux内核中,与其他类型的UNIX系统(如:Sun,SGI,HP-UX,BSD)不同,设备名中并没有使用SCSI地址。如前文所述,块设备名格式为/dev/sdln,l是表示物理设备驱动的字符而数字n代表该物理设备驱动的分区号。设备名在启动时或设备加载时按发现顺序动态指定。

 

如果添加了硬件设备之后系统重新启动,设备编号将会更改从而造成主机的挂载列表不准确。为了保持设备编号的准确性并减少挂在列表出现偏差的可能性,应当把新的设备附加在当前设备列表中。例如,如果主机包含多个HBA,最好将新设备附加在最后一个HBA的磁盘设备列表的末端,这样就无需更改挂载列表中的现有记录。如果新设备添加到第一个HBA中,那么在系统重启之后,所有设备编号都会在原有数字加一同时挂在列表记录也需随着该设备发生偏移。如果只有一个HBA,则新设备可方便地添加到原有设备列表中并相应地改变挂载列表。

 

目前Linux系统缺乏植入到内核中的、如同drvconfig或ioscan这样能够动态配置SCSI通道的命令。

重新配置Linux主机的三种方式有:

  • 重启系统

  • 卸载并重新加载HBA驱动模块

  • echo /proc文件系统

 

重启主机:

重启主机是检测新添加磁盘设备的可靠方式。在所有I/O停止之后方可重启主机,同时静态或以模块方式连接磁盘驱动。系统初始化时会扫描PCI总线,因此挂载其上的SCSI host adapter会被扫描到,并生成一个PCI device。之后扫描软件会为该PCI device加载相应的驱动程序。加载SCSI host驱动时,其探测函数会初始化SCSI host,注册中断处理函数,最后调用scsi_scan_host函数扫描scsi host adapter所管理的所有scsi总线。

 

卸载并重新加载HBA驱动模块:

通常情况下,HBA驱动在系统中以模块形式加载。从而允许模块被卸载并重新加载,在该过程中SCSI扫描函数得以调用。通常,在卸载HBA驱动之前,SCSI设备的所有I/O都应该停止,卸载文件系统,多路径服务应用也需停止。如果有代理或HBA应用帮助模块,也应当中止。

命令示例:

例如,rac节点上某台服务器执行fdisk –l命令看不到共享磁盘,可尝试执行如下命令:

# modprobe -r lpfc(卸载驱动)

# modprobe lpfc(加载驱动)

 

/proc下SCSI扫描:

2.4内核中,/proc文件系统提供了可用SCSI设备的列表。如果系统中SCSI设备重新配置,那么所有这些改变通过echo /proc接口反映到SCSI设备中。添加一个设备,主机,channel,target ID,以及磁盘设备的LUN编号会被添加到/proc/scsi/,需指定scsi编号。

命令示例:

# echo "scsi add-single-device 0 1 2 3" > /proc/scsi/scsi

0:主机ID

1:channel ID

2:target ID

3:LUN编号

该命令会将新磁盘设备添加到/proc/scsi/scsi文件中。如果没有找到相应文件,需为/dev路径下新增磁盘设备创建设备文件名。

如果要删除一个磁盘设备,使用适当的主机,channel,target ID及LUN编号运行如下格式命令:

# echo "scsi remove-single-device 0 1 2 3" > /proc/scsi/scsi

0:主机ID

1:channel ID

2:target ID

3:LUN编号



更多精彩内容,请点击阅读原文”进行查看!

如何每天都能收到如此精彩的文章?

①点击右上角点击查看官方账号”→点击关注

②长按并识别下图中的二维码,直接访问EMC中文支持论坛


 
戴尔易安信技术支持 更多文章 备份和归档的区别 云计算的三种模型:公有云、私有云和混合云 正确描述IO类型 【大咖讲网络】谁动了我的网络 浅析I/O处理过程与存储性能的关系
猜您喜欢 【技术蛋糕】Java最困扰你的那些事 编写可读代码的实践:接口篇 如何脱颖而出? 途牛原创 | 库存系统-有效数据和无效数据分离 深度学习、信息论与统计学