1.2.6 文件、目录和单目录层次结构
Ritchie 和 Thompson 在他们开创性的文章《The UNIX Time-Sharing System》中指出,操作系统最重要的作用是提供文件系统 。Kernighan 和 Pike 在他们如今已声名显赫的 Unix 环境编程著作《UNIX编程环境》中指出,Ritchie 和 Thompson 在设计 Unix 系统时讨论的第一个方面就是其文件系统的结构,因为这决定了其他所有事物的工作方式;他们甚至声称“UNIX 系统中的一切都是一个文件”。
1.2.6.1 文件
对于大多数使用计算机的人来说,文件只是存储信息的对象。这些对象通常驻留在非易失性存储设备上,这些存储设备即使在断电的情况下也能保留数据,例如磁带、磁盘、光盘和电子磁盘。(相比之下,易失性存储器,例如主存储器,在断电时不会保留数据。)这些非易失性存储设备被称为辅助存储设备或外部存储设备,即使它们在你看来似乎位于计算机“内部”。这种命名法源于历史。
在许多非 Unix 系统中,操作系统可以识别不同类型的文件,每种文件都有其特定的结构,例如文字处理文档、图像文件或电子表格。事实上,在这些系统中,文件通常具有名称或扩展名,可以用来推断其结构,甚至导致特定程序加载它们。
然而,在 Unix 中,情况却大不相同。从内核的角度来看,普通文件只是一个包含线性字节序列的对象。它不会对此类文件的内容强加任何结构;任何可能的结构都由创建它的用户或程序赋予。这些文件被称为常规文件或纯文本文件。其中一些文件就是我们通常所说的文本文件,因为打开它们时,我们看到的是纯文本。这些文件包含字符序列,行由换行符分隔;用于显示它们的程序使用嵌入的换行符在屏幕上创建行结构。二进制文件是包含不一定是文本字符的字节序列的文件,例如程序的可执行代码。
1.2.6.2 文件类型
除了这些常规文件之外,Unix 内核还定义了一小部分文件类型:
目录
设备文件
管道
套接字
符号链接
设备文件、管道和套接字统称为特殊文件。特殊文件是 Unix 文件系统的一个特殊特性。它们的发明是为了提供一种以设备无关的方式进行 I/O 编程的方法。套接字是一种允许进程之间通信的设备文件,主要用于网络通信。
1.2.6.3 文件属性、权限和内容
所有文件,无论其类型如何,都具有属性。属性包含有关文件的所有重要信息,例如文件上次修改时间、上次访问时间、所有者的用户 ID、文件大小(以字节数表示)、允许哪些人对文件进行各种类型的访问等等。描述文件访问限制的属性称为文件模式或文件权限。
文件的属性统称为文件状态。“状态”一词可能听起来有点误导,但它是 Ritchie 和 Thompson 在原始 UNIX 系统中使用的词。另一个经常用于描述文件属性或状态的词是元数据。 Unix 系统对文件的内容和状态进行了明确的区分。内容是文件的数据;大多数(但并非所有)文件都有内容。某些文件,例如设备文件和某些其他特殊文件,没有内容;它们不存储数据。它们是内核用来实现设备无关的输入和输出的接口。
文件的内容不包含任何状态信息。例如,它们没有文件结束符来表示文件结束,也没有任何其他表示文件长度的方式。内容和状态甚至不存储在一起。状态存储在称为 inode 的数据结构中,而内容可能分散在与 inode 相同的存储设备上的多个块中。
关于文件的一个重要事实是,文件名不属于文件状态。事实上,非目录文件可以有多个名称,这些名称并非文件本身的固有属性,而是包含它们的目录的固有属性。
1.2.6.4 目录
目录,在其他操作系统中通常称为文件夹,是一种文件类型,从用户的角度来看,它似乎包含其他文件。
image
这只是一种假象;目录并不包含文件,就像目录并不包含书籍的章节一样。那么,什么是目录?准确地说,目录是一个包含目录条目表的文件,这些条目是实际称为链接。链接是一个将文件名与实际文件关联的对象。它包含两个部分:文件名和对文件 inode 的引用。链接可以引用任何类型的文件,包括目录,这意味着目录可以是目录的成员。但是,链接不能引用与目录本身位于不同设备上的文件。目录永远不会为空,因为每个目录都包含两个链接,分别名为 .(点)和 ..(点-点)。这些条目具有预定义的含义:. 是指向目录本身的链接,.. 是指向包含此目录的目录的链接,该目录称为父目录。
image
左侧列中的数字仅供参考,表示对给定文件 inode 的引用。例如,drivers 是此目录中 inode 编号为 185 的文件的名称。
当您在 shell 中工作时,它会为您维护一个唯一的目录,称为当前工作目录。
ls 命令可以显示目录的内容。输入不带参数的 ls 会显示当前工作目录的内容:
image
或者,我们可以将一个或多个目录名作为 ls 的参数来查看其内容:
image
请注意,每个目录的名称都先出现,然后是该目录中的文件。 ls 使用的列数取决于目录中名称的数量及其长度。
我们可以使用 cd 命令更改当前工作目录:
image
请注意,现在 ls 命令显示的是新工作目录(即 chapters)的内容。我们可以通过.. 链接返回上一个目录:
image
ls 的输出显示工作目录再次成为 chapters 的父目录,因为文件名列表与我们将目录更改为 chapters 之前相同。
1.2.6.5 文件名
如前所述,文件和文件名是不同的东西。文件名是用于命名文件的字符串。它是目录中链接的一部分。一个非目录文件可能在不同的目录中(在同一逻辑设备上)拥有名称,因此看起来像是多个目录的成员。
但是,文件的存在与它们所在的目录无关。如果同一个文件在不同的目录中拥有名称,则链接中与这些名称关联的引用都指向同一个 inode,即该文件的唯一 inode。这就像一个人带着几本护照旅行。这些护照可能代表不同的人,并且在不同的国家/地区使用,但它们代表同一个人。
image
在此图中,一个文件有三个不同的名称,每个名称都是指向不同目录的链接。文件名可以很长。文件名的最大字符数由系统相关的常量 NAME_MAX 定义,通常为 255 个字符。文件名可以包含除正斜杠 (/) 和空字符 (\0) 之外的几乎任何字符,但即使允许,也不应该在文件名中使用某些字符。例如,文件名可以包含空格和换行符,但如果包含空格和换行符,通常需要用引号将文件名括起来,以便将其用作命令的参数。某些字符(例如 $、&、* 等)对不同的程序具有不同的含义,如果在这些环境中使用,则必须在它们前面加上反斜杠进行转义,所以最好避免使用它们。惯例是在文件名中只使用字母数字字符、下划线和连字符。
Unix 区分大小写,因此 source 和 Source 会被视为两个不同的文件名。
与大多数其他操作系统不同,Unix 不使用文件扩展名用于任何目的,尽管编译器和文字处理器等用户级软件可能会使用它们作为参考。GNOME 和 KDE 等桌面环境可以基于文件扩展名创建关联,其方式与 Windows 和 macOS 大致相同,但 Unix 本身没有基于内容的文件类型概念,它为所有文件提供相同的操作集,无论其类型如何。在 Unix 中,我们使用单词suffix 来表示文件名中句点后的部分,例如 myprog.c 中的 c。
1.2.6.6 目录层次结构
Unix 将文件组织成树状层次结构,大多数人错误地将其称为文件系统。更准确地说,它应该称为目录层次结构,因为“文件系统”一词指的是写入非结构化磁盘设备上的一组数据结构,用于创建和管理文件和目录。这个树状层次结构中的每个节点要么是非目录文件,要么是目录。每条边都是一条有向边,从非空目录到该目录包含的每个文件(包括目录文件),我们将包含的文件称为该目录的子节点。
目录被称为这些子节点的父节点。这个层次结构的基目录是一个根目录,其名称为 / 字符。即使基目录名为 /,当人们提到这个目录时,他们通常称之为根目录,因为“斜杠”不太直观,而且读起来也比较拗口。
由于单个文件可以在不同的目录中使用同一个名称,因此一个文件可能有多个父节点。这就是为什么层次结构类似于树形结构但并非真正的树形结构,因为在树形结构中,每个节点都有一个唯一的父节点。
在典型的现代 Unix 系统中,目录层次结构是一个有向无环图,即一个不含环路的有向图。它之所以不含环路,是因为目录与非目录文件不同,它不能拥有多个名称,这意味着它只能位于一个父目录中。这意味着任何后代节点都不能指向它,因此该图不含环路。某些 Unix 实现允许超级用户为目录赋予多个名称,在这种情况下,层次结构可能存在环路。
单一目录层次结构的概念是 Unix 的一个定义性特征。其他操作系统,例如 Microsoft Windows,为每个不同的设备都设置了单独的目录层次结构。在 Unix 中,即使这棵树中的文件可能位于不同的设备上,任何设备上的目录层次结构都可以通过一个称为挂载的过程连接到这棵树上。
挂载到树上后,其文件就可以像访问所有其他文件一样被访问。典型的 Unix 目录层次结构在根目录下有多个目录。这些目录被称为顶级目录。
image
以下列表描述了大多数 Unix 系统中存在的顶级目录。 POSIX.1-2024 实际需要的目录只有/dev 和 /tmp。
bin: 所有必需的二进制可执行文件,包括计算机在单用户模式(类似于 Windows 中的安全模式)下运行时必须可用的 Shell 命令。
boot 引导加载程序的静态文件。
dev 必需的设备文件。
etc: 几乎所有主机配置文件,大致类似于 Windows 的注册表文件。
home 所有用户的主目录(如果存在)。
lib: 必需的共享库和内核模块。
media:可移动介质的挂载点。
mnt
临时挂载文件系统的挂载点。
opt: 附加应用软件包。
sbin: 必需的系统二进制文件。
srv: 系统提供的服务数据。
tmp: 应用程序创建的临时文件。
usr: 最初,它是用户数据文件层次结构的顶层,但现在它位于包含非必要二进制文件、库和源代码的层次结构的顶层。典型的子目录有:/usr/bin 和 /usr/sbin,包含二进制文件;/usr/lib,包含库文件;以及 /usr/local,位于第三层本地程序和数据的顶层。
var: 可变文件,指内容可以更改的文件。
所有文件,包括目录,都可以通过两个独立的二进制属性来表征:可共享性和可变性。可共享文件可以存储在一台主机上,并在其他主机上使用。不可共享文件则不可共享。例如,用户主目录是可共享的,因为它们不依赖于它们的存储位置,而引导加载程序文件特定于给定的机器,并且不可共享。
可变文件是内容可以更改的文件,而静态文件是内容不能更改的文件。例如,它们包括可执行二进制文件、库、文档文件以及其他在计算机日常运行中通常不会更改的文件。在现代 Unix 系统中,文件的可共享性和可变性是决定哪些文件位于层次结构的哪些部分的因素。具有这两种属性之一的文件被放置在不同的目录中,这使得在不同文件系统上存储具有不同使用特性的文件变得容易,也使备份更容易。例如,/etc 目录是不可共享的——它包含特定于特定计算机的文件——并且它是静态的,因为它的内容是配置文件,只有在我们应用更新、安装新软件或超级用户决定更改配置时才会修改。 /var 目录之所以如此命名,是因为它是可变的。它包含许多不同类型的日志文件,内核和应用程序会定期更新这些日志文件。它的某些子目录(例如 /var/mail)可能是可共享的,而其他一些子目录(例如 /var/log)则可能是不可共享的。/usr 目录是可共享的静态目录。它包含应用程序二进制文件、库和静态数据。
1.2.6.7 符号链接
普通链接是指向文件 inode 的目录条目,而符号链接的内容仅仅是另一个文件的名称。链接指向的文件称为链接的目标。符号链接的 inode 将该文件标识为符号链接。它类似于 Windows 操作系统中的快捷方式。符号链接通常称为软链接,而普通链接则称为硬链接。
通常,当命令、程序和内核本身在预期文件名的情况下被赋予符号链接时,它们将对链接的目标而不是链接本身进行操作。它们很容易看出该文件是符号链接,因为 inode 指示了这一点。当打开链接访问其目标时,我们说链接被取消引用或被跟踪。
符号链接会给操作系统和应用程序带来风险,因为它可能存在循环引用和无限循环。危险在于符号链接可能指向目录,这意味着如果程序跟踪符号链接,它可能会返回到它已经访问过的目录,最终陷入循环。
1.2.6.8 路径名
路径名是标识文件的字符串。路径名有两种类型:绝对路径名和相对路径名。绝对路径名从目录层次结构的根目录开始,并以斜杠 / 开头。以斜杠开头的斜杠后跟零个或多个文件名,例如/data/jammy/kernel/sched/sched.h。除最后一个文件名外,所有文件名都必须是目录名或以目录名为目标的符号链接。示例路径名中除 sched.h 之外的每个名称都是目录。路径中的最后一个名称可以是任何类型的文件。其他绝对路径名示例包括 /usr/bin/、/usr/local/share/man 和 /home/stewart/unixbook/figures/figure01.png。
如果路径名中的最后一个文件名是目录,则可以用斜杠终止路径名,例如路径名 /usr/bin/。
如果您在路径中的名称之间意外插入了多个斜杠,它将被忽略。两个绝对路径名 /usr/local/share/man和 /usr/local///share/man 是相同的。
如果路径名不以斜杠开头,则称为相对路径名。相对路径名从当前工作目录开始,我们现在可以准确地定义它了。当前工作目录(也称为
当前工作目录)是任何正在运行的程序用来解析不以 / 开头的路径名的目录。例如,如果当前工作目录是/home/stewart/unix_book,则路径名 chapters/chapter_01指向一个绝对路径名为 /home/stewart/unix_book/chapters/chapter_01 的文件。
环境变量 PWD 包含当前工作目录的绝对路径名。 pwd 命令打印 PWD 的值:
$ pwd
/home/stewart/unix_book
$ printenv PWD
/home/stewart/unix_book
如果路径名包含符号链接,路径名可能会变得很长,而Unix 系统会限制路径名的长度,以字节为单位。POSIX.1-2024 规定,常量 PATH_MAX 是路径名允许的最大字节数,包括终止 NULL 字节。在许多 Linux 系统上,该值是 4096 字节。
1.2.6.9 进程
程序是用编程语言编写的一系列指令序列,这些指令序列发送给计算机。编程语言可以是高级语言,例如 C 或 C++,也可以是低级语言,例如汇编语言。通常,程序不能以其编写的形式直接执行;必须先将其转换为可执行文件。例外情况是用脚本语言编写的程序,例如 JavaScript、PHP 和 BASIC。这些程序不会被转换为可执行文件;解释器程序会直接读取源代码,并逐行执行其中的指令。我们将程序的第一种形式称为源代码,将第二种形式称为可执行代码,或者简称为可执行文件。
大多数程序的可执行形式并不是我们真正可以运行的。我们不能直接将其加载到内存中,然后告诉机器从它的第一个字节开始运行该文件。该文件通常由可执行代码、各种表以及链接器/加载器指令组成。当你输入命令 $ ./hello_world 时,会发生一系列操作,使链接器/加载器使用 hello_world 可执行文件中的信息将文件及其所需的任何共享对象加载到内存中,准备执行程序,并运行该程序。
多个用户可以在给定的机器上同时运行一个程序,或者单个用户可以在不同的终端窗口中多次运行一个程序。无论哪种方式,都意味着一个可执行文件可以有多个正在运行的实例,这引导我们区分程序和进程。进程是正在运行的程序的一个实例。每个单独的实例都是一个不同的进程,尽管它们都在执行同一个可执行文件。
这个进程的正式定义并没有真正告诉你进程的具体含义这就像将棒球比赛定义为亚历山大·卡特赖特 (Alexander Cartwright) 于 1845 年创建的规则集的一个实现实例,该规则集规定两支球队在运动场上相互竞争。这两种定义都无法让您清楚地了解所定义的内容。让我们更具体一点。
当程序在计算机上运行时,它会使用各种资源,例如主内存和辅助存储空间;内核内存(内核空间),用于各种映射和表,例如它使用主内存哪些部分的表;权限,例如读取或写入某些文件或设备的权限;等等。因此,在任何时刻,一个进程都与分配给正在运行的程序实例的所有资源的集合相关联,以及表征该实例的任何其他属性和设置,例如处理器寄存器的值。因此,尽管进程的概念听起来很抽象,但实际上它是一个非常具体的事物,操作系统必须对其进行管理。
Unix 系统为每个进程分配一个唯一的非负整数,称为进程标识符,简称 PID。我们可以使用 ps 命令来了解一些有关进程的知识,该命令可以显示正在运行的进程列表,以及每个进程的特定信息。它有各种选项来控制显示哪些进程以及输出哪些信息。在最简单的形式下,即不使用任何选项,我们可以使用它来查看我们自己正在运行的进程的 PID:
image
这列出了两个进程:一个运行 bash,另一个运行 ps 命令本身。它们耗时极短,显示为零,它们的 PID 分别为 10278 和 11087。它们都运行在设备名为 pts/0 的终端中。
我们可以调用 getpid() 函数来获取调用它的进程的 PID。我们在 getpid_demo.c 程序中演示了这一点:getpid_demo.c。
include
include
intmain()
{
printf(“I am the process with process-id %d\n”, getpid());
}
系统调用声明位于 中。这是我们第一个进行系统调用的程序。getpid() 的返回值是调用它的进程的 PID。由于 PID 在 printf() 的格式字符串中是整数,因此我们使用 %d 格式规范将返回值打印为固定的十进制数字。
gcc getpid_demo.c -o getpid_demo
./getpid_demo
I am the process with process-id 59592
如果我们再次运行同一个程序,它将打印不同的 PID,这证明每次运行它时都会创建一个新的进程。
1.2.6.10 线程
控制线程是程序执行过程中逐条执行的单个指令序列。最初,所有程序都只有一个控制线程。随着计算机处理器成本越来越低,硬件供应商开始构建包含多个处理器的计算机,计算机科学家也开始探索利用这项新技术的方法。他们设计并创建了编程语言和库,允许程序包含多个控制线程,每个控制线程可以在不同的处理器上同时运行。为了简单起见,这些控制线程被称为线程。
POSIX.1-2024 将线程正式定义为进程的单个控制流,以及支持该控制流所需的系统资源。传统的 Unix 进程是单线程的,但在现代操作系统中,进程通常可以包含多个线程。当一个进程拥有多个线程时,它被称为多线程进程。多线程进程有两种类型的资源:其所有线程共享的资源,通常称为全局或共享;以及每个线程独有的资源,通常称为线程本地资源、私有资源或单线程资源。
Unix系统通常支持多线程,Linux尤其支持几种不同类型的线程。Linux以一种有趣的方式处理线程;它将所有线程视为标准进程。它没有为线程提供任何特殊的调度或数据结构。对于Linux内核来说,进程和线程都称为任务,并且在内部都由同一个数据结构task_struct 表示。在Linux中,任务是一个被分配了系统资源并可以在处理器上进行调度的实体。Linux中线程和普通进程的区别在于,线程可以共享资源,例如它们的地址空间,而进程不共享任何资源。
在许多 Unix 实现中,每个线程都有一个线程标识符 (TID),该标识符在操作系统中是唯一的,但 POSIX.1-2024 对此没有要求。它只要求在单个进程中,每个线程的 TID 都是唯一的。Linux 采用双管齐下的方法处理 TID:在单线程进程中,TID 等于进程 ID;而在多线程进程中,所有线程具有相同的 PID,但每个线程都有一个唯一的 TID。在 Linux 中,线程可以调用 gettid() 函数来获取其线程 ID。gettid_demo.c 程序演示了这一思路:
include
include
include
intmain()
{
printf(“I am a thread with thread-id %d\n”, gettid());
}
该程序使用 C 预处理器 #define 指令来定义符号 _GNU_SOURCE。除非定义了此符号,否则编译器将无法识别头文件中程序调用 gettid() 所需的各种声明。这是一个功能测试宏的示例。#define 指令必须出现在所有 include 指令之前。我们可以按照以下示例会话所示编译并运行该程序:
gcc gettid_demo.c -o gettid_demo
./gettid_demo
I am a thread with thread-id 59608
如果我们再次运行该程序,它每次也会显示不同的 TID,原因与之前相同:一个新的进程运行,当它只有一个线程时,它的 TID 与它的 PID 相同。
1.2.6.11 在线文档
Unix 系统提供了几种不同类型的在线文档。在此上下文中,“在线”指的是你正在使用的电脑,而不是万维网。
手册页
1971年,在UNIX第一版发布后不久,Dennis Ritchie和
Ken Thompson在Joseph Ossanna和Robert Morris的帮助下编写了第一本UNIX程序员手册,该手册至今仍可在线获取 (https://
www.nokia.com/bell-labs/about/dennis-m-ritchie/1stEdman.html)。这本手册初只有一卷,但很快就发展成为一套七卷本,按主题组织。
随着时间的推移,它的规模不断扩大。现在每个 Unix 发行版都附带这套手册页,简称 man 页面。截至撰写本文时,典型的 Unix 系统中的手册页通常包含八个编号的章节,如表 1-1 所示。某些 Unix 系统还会添加其他章节。
image
手册页是 Unix 文档的重要组成部分。当你想了解 Unix 系统的任何部分时,它们可以作为在线参考,例如某个命令、某个库中的函数、系统调用、设备接口、系统文件、各种文件格式等等。
虽然文档非常详尽,但通常并非教程性质。有时,它可能会让人不知所措,但许多页面都包含可以编译、修改和运行的代码示例。
在我教授 Unix 系统编程的这些年里,学生们有时会说,他们不需要学习如何使用手册页,因为所有信息都在网络上,他们只需谷歌一下即可。诚然,您可以在许多网站上找到手册页的副本,并在讨论区阅读帖子,但阅读您自己安装的 Unix 系统上的手册页的原因远不止于此:
您系统上的手册页版本是在安装其所记录的软件时安装的,并且每当您更新软件本身以及软件有更新需要应用时,手册页都会更新。
手册页由编写和维护软件的人员编写,值得信赖且准确。
您系统上的手册页是独立的,因为其中的任何交叉引用也都存储在您的系统中。
即使您的互联网连接不可用,您也可以阅读它们。
要查看给定主题的手册页,请输入 man,后跟您感兴趣的主题,即命令名称、函数名称等等。例如,输入 man man 即可阅读 man 命令本身的手册页:
image
输出仅包含该页面的前几行。第一行显示,man 命令位于手册页的第 1 部分,因为标题包含 MAN(1)。文本 Manual pager utils 并非第 1 部分的名称;我们将其称为手册页标题或页眉(含义清晰时)。第 1 部分中的不同手册页可能具有不同的页眉。NAME 之后是命令的名称,其后是该命令功能的简要描述。这是您应该阅读的第一个手册页,我们稍后会再次讨论它。
所有符合 POSIX 标准的 Unix 系统都必须包含内核 API 函数可能包含的所有头文件的手册页。更准确地说,POSIX.1-2024 系统接口卷中的每个函数都指定了应用程序必须包含的头文件才能使用该函数,并且符合 POSIX 标准的系统必须为每个头文件提供相应的手册页。这些头文件可能未安装在您使用的系统上,但它们是可用的。只有系统管理员安装了应用程序开发文件后,才会安装它们。
scanf() 函数的手册页以以下几行开头:
image
它告诉我们需要头文件 stdio.h 才能使用 scanf()。我们可以输入man stdio.h 来查看该头文件,输出如下内容:
image
请注意,本手册页位于编号为 7posix 的章节中。在您的系统上,该页面可能位于其他章节,例如第 0 节。
使用手册页的一个挑战是,您需要知道您感兴趣的命令或函数的名称,这样它们才能对您有所帮助。手册页确实有一个相对简单的搜索机制,但它们实际上是为那些已经知道需要查找什么的人提供的参考手册,所以如果你知道你想要什么如果想做,但不知道命令名称,那么难点在于如何找到它。
手册页在帮助您自行解决问题方面发挥着关键作用。我教授如何编写系统程序的方法是基于使用手册页来指导学习过程。本书中,手册页与学习系统编程密不可分,因此我在第34页单独设立了一个章节“使用手册页”,更深入地解释了手册页的结构以及如何使用它们,包括用于指定选项和参数的语法。
Info 文档系统
由于手册页存在一些缺陷,GNU 项目开发了一个名为 Info 的替代文档系统,该系统基于 Texinfo 文档系统。Texinfo(发音为“Tekinfo”)是一个使用单个源文件生成在线和打印输出的文档系统。它基于 Richard M. Stallman 于 1975 年和 1976 年为 Emacs 文本编辑器创建的帮助系统 (https://www.gnu.org/software/texinfo/manual/texinfo/html_node/History.html)。它的各种命令和实用程序的信息页有时比其手册页包含的信息多得多。在某些情况下,某个命令的手册页会引导读者查看信息页。要阅读信息页,请输入 info 命令(小写)。例如,要了解 ls 命令,请输入 info ls:
image
当信息系统中没有某个主题的页面时,信息阅读器会打开该主题的手册页。
信息页面使用类似于 Emacs 中的导航方法,但人们通常觉得这种方法难以使用。有一种读取信息文档的方法,并通过将其输出通过管道传输到寻呼机程序(例如 more 或 less)中来绕过其中的导航,如下所示:
image
显示相同的信息,但还会提及包含该信息的文件:coreutils.info。
应用程序提供的文档
有时,您还可以在 /usr/share/doc 中的某个目录中找到有关特定应用程序或程序的信息。许多应用程序和更高级别的程序安装程序将其文档放在那里。这些文档有时包含大量的使用示例、开发说明以及有关在何处查找更多信息的提示。
某些命令可以显示其自身的帮助,通常通过提供诸如 –help 之类的选项来显示:
image
其余输出主要描述 ls 的各种选项及其参数。
Shell 帮助
某些 Shell 具有内置命令的帮助功能。特别是,bash 有一个 help 命令,当不带参数输入时,它会打印一个包含所有 bash 内置命令的两列列表,其中包含选项和参数:
image
当给定特定 bash 内建命令的名称时,它会打印该命令的简短使用方法:
$image
help 命令使用与man相同的语法。
其他文档来源
您可以从编写和维护代码的组织下载许多手册。其中最重要的手册是《GNU C 库参考手册》,可在 https://www.gnu.org/software/libc/manual/ 获取。
声明:来自pythontesting,仅代表创作者观点。链接:https://eyangzhen.com/1549.html