一次性付费进群,长期免费索取教程,没有付费教程。
进微信群回复公众号:微信群;QQ群:460500587
教程列表 见微信公众号底部菜单 | 本文底部有推荐书籍微信公众号:计算机与网络安全
ID:Computer-network
点击鼠标按键与看到屏幕上发生的事情之间的联系是复杂的。简而言之,需要某种软件进程,这些进程在鼠标与计算机之间、计算机及在其之上运行的软件之间、软件与屏幕之间来回地传送数据。
不仅是传送数据,还需要一种在只知道自己所在桌面的鼠标与只知道0和1的软件之间转换数据的方法。再乘以成千上万种类型的设备,加上许多类型的连接(PCI、SATA、USB、串行口),在计算机里已经将自己弄得焦头烂额了。
考虑到整件事情的复杂性,一切都在可靠地运行就是一个奇迹了。本文将学习如何应对它那些不可靠的时刻,如同营销团队正在等待激活网络摄像头来开始他们虚拟会议的时刻;或者是,他们的WiFi一开始就不让他们连接的时刻。要施展所有的这些魔法,需要明白Linux是如何看待外围设备的,以及如何引导Linux内核将一个有些胆怯的设备放在它的羽翼下并加以照顾。因为我们关心所有的设备。
1、识别连接的设备
操作系统(OS)有时甚至不能识别一些已连接的硬件。如果一个已插入的设备看上去不能工作,要做的第一件事情就是确认Linux是否已经知道该硬件在那儿了。如果问题依然存在,请考虑如下可能性:
● 该设备与硬件或Linux不兼容。
● 该设备已损坏或者存在故障。
● 硬件接口或线缆已损坏或存在故障。
● 系统需要重新启动。
一旦它们彼此通信,将展示如何使用内核模块,以使Linux及设备能够协作完成某些工作。我们将用Linux之眼来查看硬件。可以用lsblk命令来发现已连接的块设备。lsblk命令还有一些表亲:lsusb命令列举出Linux感知到的任何USB设备,lspci命令将对PCI设备进行相同的操作。以下是一个示例:
当以root权限运行时,lshw命令会打印出完整的系统硬件配置文件。将注意的第一件事情是,lshw命令会对每个硬件给出极大数量的信息。驯服这头野兽的一个方法是将输出转换为易读的.html文件,从而可以在Web浏览器中进行查看。-html参数用以实现这一功能。在诸如Nautilus等的GUI文件管理器中,点击文件名会将该文件装载到默认的浏览器中。如下是操作方法:
使用lshw-class network命令将输出限制为仅为网络相关的内容,该技巧对其他数据子集也是有效的。例如,lshw-c memory命令显示了系统使用的所有类型存储器的详细信息(包括RAM、BIOS固件以及高速缓存)。-c参数是-class的简洁替代。除此之外,lshw-c storage命令还会显示SATA和SCSI接口上的信息,-c multimedia包括音频和视频设备,-c cpu参数会给出关于主板上CPU的一切。
这里有一个常见场景。假设正在考虑为系统扩展内存(RAM)。需要知道,已有多少内存以及它是什么类型,而不用关心正在使用的是什么主板,以及由此可以查出有多少可用的内存槽及其最大容量是多少。
内存并非是一种合适的外围设备,但它作为硬件发现的例子是很好的。在解决硬件问题时,硬件发现应该总是第一个步骤。
以实例说明,lshw命令显示出主板共有4个内存插槽,其中2个已被4GB的A-Data DDR3 1600内存模块占用。因为要尽力避免在系统中安装不匹配的内存模块,这个结果准确地告诉我们应该为那2个可用的插槽购买什么类型的内存,以使内存的容量加倍。
如果设备已被Linux识别但仍然不能工作,该做些什么?或许,有一个合适的内核模块正在等待加载。
2、用Linux内核模块管理外设
Linux使用内核模块来管理硬件外设。以下是其工作原理。
内核是驱动计算机做所有事情的软件。考虑到在一个运行的系统中同时要管理很多细节,让内核在尽可能少的干扰下完成其工作会更好。但是,不重启整个系统就不可能对计算环境进行哪怕是非常小的改动,那么,插入一个新的摄像头或打印机可能会对工作流造成令人不悦的破坏。每次添加设备时,都必须重启以使系统能够识别硬件,这一方式的效率很低。
为了在可用性和稳定性的相对优点之间建立有效的平衡,Linux隔离了内核本身,但是允许通过可加载内核模块(Loadable Kernel Module,LKM)来动态添加特定的功能。如图1,可以将模块看作一个软件,它会告知内核在哪里找到设备以及如何使用它。反过来,内核将设备提供给用户和进程,并监督其操作。
图1 内核模块作为设备和Linux内核之间的转换器
没有什么能阻止编写自己的模块以所希望的方式来支持某个设备,但为什么要这么麻烦呢?Linux的模块库已经非常强大了,因此,通常并不需要推出自己的模块库。而且,大多数时候,Linux会在不知情的情况下自动加载新设备的模块。
尽管如此,还是会有一些时刻,因为某种原因它并不会自行发生。为了促进这些事情,会想更多地理解内核模块,尤其是如何找到能让该外设真正运行的模块,之后是如何将其手动激活。
(1)查找内核模块
根据公认的惯例,模块是带有.ko(内核对象,kernel object)扩展名的文件,且位于/lib/modules/目录中。但在向下浏览这些文件之前,可能不得不先做出一个选择。因为启动时会让从发布列表中进行选择,用以支持选择(包括内核模块)所需的特定软件必须在某个位置存在。/lib/modules/目录就是这些位置中的一个。而且,在这个位置将找到以每个可用的Linux内核版本的模块填充的目录,如下:
例子中,该活动内核具有发行号4.4.0-104-generic的版本。如果想在一个实时系统上使用一些模块,需要确保已经得到了正确的目录树。
有一个可靠的技巧。除了用名字识别目录并期待得到正确的那个,还可以使用指向活动内核名字的系统变量。可以用uname-r命令调用这个变量(-r参数指定系统信息中常规显示的内核版本号):
有了这些信息,就可以使用称为命令替换(command substitution)的进程将uname命令合并到文件系统引用中。例如,要导航到正确的目录,可以将其添加到/lib/modules。要告诉Linux,uname本身并不是一个文件系统位置,那就请将uname括在反勾号中,如下所示:
大多数模块本身都组织在kernel/目录下,它们自己的子目录中。现在,请花一点时间浏览这些目录以了解它们是如何组织的以及有什么是可用的。文件名通常会很好地了解到您正在看什么:
这是定位内核模块的一种方法,实际上是一种快速但不高明的方法。但这并不是唯一的方法。如果要获取完整的集合,可以用lsmod命令列出所有已经加载的模块以及一些基本信息。第一列是模块名,其后是文件大小和数量,之后是所依赖模块的名称:
我们再运行一次lsmod命令,但这一次将输出结果用管道传递给wc-l命令来统计行数:
这些都是已加载的模块。总共有多少可用的模块呢?请运行modprobe-c命令并统计行数就可以告诉我们数量:
有33350个可用的模块吗?看样子多年来已有人在非常努力地工作,为我们提供了运行我们物理设备的软件。
在某些系统上可能会遇到一些定制的模块,这些模块或者引用/etc/modules文件中自己的唯一条目,或者引用保存在/etc/modules-load.d/目录中的配置文件。这些模块极有可能是本地项目开发的产物,其中可能包含了尖端实验。
这就是如何查看模块的方法。下一个工作是如何手动加载一个不活动的模块,如果其因为某种原因没有自己完成的话。
(2)手动加载内核模块
在能够加载内核模块之前,逻辑上要求先得确认该模块是存在的。而在确认之前,得先知道其名称是什么。有时候,获取这些信息可能需要同等份的魔力和运气,以及来自在线文档作者的一些帮助。
笔记本的WiFi接口突然停止了工作,也许是更新软件让其崩溃了。运行lshw-c network命令得到了如下非常奇怪的信息:
Linux识别了这个接口(Atheros AR9485)但将其列入未托管的类别。如他们所说,“当事情变得棘手时,就需要在互联网上进行搜索。”最终发现,至少在Ubuntu 16.04上存在一个工作的模块。其名称为:ath9k。
为了再次确认该模块是可用的,可以在模块的目录树中运行find命令,-type f参数告知Linux正在查找一个文件,之后添加带有一个通配符的字符串ath9k,以包括所有用该字符串开头的文件名:
再进一步,加载该模块:
就是这样。不用重启。
另一个示例展示了如何处理已经崩溃的活动模块。有一次,当用一个特定软件来使用逻辑网络摄像头的时候,会造成其他程序在下一次启动系统之前都不能访问该摄像头。有时,需要在不同的应用程序中打开摄像头,且没有时间来关机、再启动。
因为这个模块可能是活动的,使用lsmod命令查找video一词给了有关模块的名称提示。实际上,其好过一个线索——用video一词描述的唯一模块是uvcvideo,如下所示:
用rmmod命令杀死了uvcvideo模块,并用modprobe命令将其再次启动:
不用重启。无须麻烦地处理。
3、引导时手动管理内核参数
由于我们正在讨论内核,所以现在就是认真讨论内核参数的好时机。内核参数听起来很可怕。是的,它们确实很可怕:把它们弄错至少会让计算机暂时无法启动。拼写也很重要。
内核的默认引导配置有时并不能正常工作,修复它的唯一方式就是改变内核的引导方式。
在引导时,有两种方式可以把定制的参数传递给内核。一种是在引导过程中编辑GRUB菜单项,而另一种则是在系统运行时编辑/etc/default/grub配置文件,所做的修改将在下一次启动时生效。为了说明每一种方法,将采用两个实践用例场景。
(1)引导时传递参数
有时发现不能正常地关闭或重启Linux系统,每次都会遇到意外的系统冻结。有时,添加一个简单的内核参数就会解决这个问题。以下给出说明。
在GRUB菜单(如图2所示)中想要引导的Linux版本上,按下e键就会转入一个编辑界面。在那里可以使用常规的光标及文本按键来导航和编辑内容。
图2 GRUB主菜单显示多个可被加载的Linux内核
向下滚动直至到达高亮的Linux选项,如图3所示。本例中,在换行之后,该条目以ro结尾。之后将reboot=bios添加到该行的末尾并按下Ctrl-x组合键来接受修改并进行引导。如果这还不能修复关机问题,可以再次尝试使用参数reboot=pci,而不是reboot=bios。
图3 显示引导参数的Linux行,将GRUB指向一个Linux映像的位置
要牢记,这个编辑并不是永久的。在下次启动之后,GRUB设置将再次由文件系统中的配置文件来控制。
(2)通过文件系统传递参数
有时候想启动一个没有GUI的桌面计算机。可能这个GUI本身的一些元素没有正确加载,需要一个干净的、可靠的shell会话来进行故障排除。可以通过GRUB将默认运行级别设置为3(多用户,非图形模式)。
运行级别(run level)是一个设置,它为特定会话定义了Linux的系统状态。选择0~6之间的运行级别决定了哪些服务会是可用的,从完全图形化的多用户系统到根本没有服务(意味着关机)。
打开/etc/default/grub文件,并查找GRUB_CMDLINE_LINUX_DEFAULT行。其一般提供两个参数,看起来如以下形式:
在该行的末尾添加systemd.unit=runlevel3.target,使其看上去如下所示(quiet splash并不以这样或那样的方式让我们对其感兴趣;它控制引导时屏幕上的显示内容):
在Ubuntu系统上运行update-grub命令或者在CentOS上运行grub2-mkconfig命令可以使这些改动生效。下一次启动计算机时,将会进入命令行shell。一旦解决了这些问题,就可以从/etc/default/grup中移除systemd.unit=runlevel3.target,再次更新GRUB并重启。
4、管理打印机
在更新过的底层引擎中lp依然可用,当然,它还能够做一些有趣的事情。所有的UNIX打印系统(CUPS)都是通用的。先看几上lp命令示例。
(1)lp基础
假设远程计算机上有一个文件需要打印。使用lpq命令列出可用的打印机(以及当前的工作队列):
随后,用lp命令打印文件。如果系统中有多台打印机,还需要指定要使用的打印机。以下是一个示例:
如果不想立即打印,调度它晚些再打印。-H调度设置常常使用UTC时间而非本地时间:
(2)使用CUPS管理打印机
以前,在购买一台打印机并与Linux系统一起使用之前,需要仔细并花点时间进行搜索,以确认其是兼容的。如果兼容,通常需要下载并安装正确的驱动程序,随后在操作系统上手动安装该打印机。如果打印机可以正常工作,这是值得庆祝的。近几年中,有三件事情的发生让Linux系统上的打印变得更好了:
● CUPS模块化打印系统已经被很多Linux发行版所采用,用以管理打印机及打印任务。苹果公司代表社区管理CUPS。CUPS接口极大地简化了管理和故障排除工作,同时也是相当可靠的。
● 现在,主要的打印机厂商通常都提供了Linux驱动程序。它们并非总是完美的,但是可以工作的。这意味着,几乎现代的任何打印机现在都可以被部署在Linux计算机上。
● 从17.04版本开始,Ubuntu开始提供无驱动打印。这意味着任何一台可访问的本地或网络打印机都将被自动添加到CUPS,不需要安装任何软件。
无论如何,通过浏览器访问CUPS接口,将其指向计算机的631端口(localhost:631)。Administration选项卡包含了用于管理查找、保护、调度和跟踪所有打印机的直接链接。
甚至可以管理类中的打印机组,从而允许有效地使用多台设备。这可能是一个组织资源的极好方式,例如,确保更昂贵的彩色打印只用于高优先级的作业,草稿文件则被迫在更便宜、更低质量的打印机上打印。
CUPS会无形地处理所有烦琐的管理细节。如果需要将一台特定的打印机从一台计算机(或网络子网,如果它是一台网络打印机)分离并将其添加到另外一台计算机(或网络子网),将只需在宿主计算机上的CUPS接口中做一些相应改动。正确的路由信息将在一两分钟内在该网络中自动更新。
CUPS知道哪些打印机是可用的,因为默认地,运行CUPS的打印机连接到任何计算机时都会向网络中的它的他成员广播它的存在。这一点以及许多其他的配置设置都可以由/etc/cups/cupsd.conf文件进行控制,如图4所示。
图4 /etc/cups/cupsd.conf配置文件片段
如果CUPS无法识别某一台打印机,在互联网搜索之前(使用打印机的名字及关键词linux)也可以尝试如下操作:
● 检查错误消息。运行systemctl status cups命令是查看最近警告的一个好方法。
● 在命令行运行lsusb命令(假设是USB打印机)或lpinfo-v命令,以确认系统找到了打印机。
● 确保/etc/cups/printers.conf文件中没有重复的或失效的条目。如果有,请关闭CUPS(systemctl stop cups),保存原始文件的副本,随后删除这些旧条目。再次启动CUPS,并尝试从浏览器接口添加打印机。
● 确保/etc/cups/cupsd.conf文件的字段没有任何过度严格的设置,以防其可能会阻止合法请求。
微信公众号:计算机与网络安全
ID:Computer-network
【推荐书籍】