Linux系统初识

本文主要内容:计算即架构,软件与硬件基础,Linux历史、哲学思想等,以及FHS

Linux是一个操作系统(Operating System),主要负责分配底层硬件的抽象能力,协调各个程序的运行的程序1

然而对于刚入门的我们而言,这个回答似乎并没有让我们明白,遂本文章将从最基础的概念开始说起,说明该问题。

其实我曾一直有一个疑问,为什么大部分的书籍都会在第一章介绍历史,大部分人对此并不是特别关心,“浪费”时间去读这些有必要吗?现在认为是有必要的,就如前面已经回答了Linux是什么的问题,但是新人依然一知半解,了解一下环境与历史可以直接减小我们对于一个新事物的畏惧(窃以为该畏惧几乎全部来自于未知!)Linux

一、操作系统基础

1. 计算机硬件

1.1 冯·诺依曼结构

冯·诺依曼结构(Von Neumann architecture)是一种将程序指令存储器和数据存储器合并在一起的计算机设计概念结构。现代的计算机系统(包括手机等便携式终端)的基础架构几乎都是以此设计的,其结构如下:
冯·诺依曼结构
根据该体系,计算机硬件分为5部分:

  • 运算器(Arithmetic Logic Unit
  • 控制器(Control Unit
  • 存储器(Memory
  • 输入设备(Input
  • 输出设备(Output

我们通常意义上的所谓的 CPU(Center Processing Unit) 事实上负责的就是运算器与控制器的工作,他就像动物的大脑一样,计算数据,发送各种控制指令,其主要运算工作有其内部的一个非常重要的部件 累加器(Accumulator) 完成;控制工作主要由总线对外传输(后续会详细说明)

CPU运算数据的来源或结果,将存储在存储器中,即我们所说的 内存(Memory) 。众所周知,目前的计算机几乎都是由电来驱动,故内存在计算机断点后将无法保存数据。以上三项构成了计算机最核心的部件。

输入设备与输出设备,我们通常将其和称为 I/O(Input/Output)设备 ,负责计算机与外界交互,如将计算结果输出到屏幕,或录入数据,如打字,相信很好理解。2

1.2 CPU缓存

由于技术工艺原因,存储器(内存)的速度与CPU的速度差距甚远,由此CPU在与内存交互式将产生严重的性能浪费,即 冯·诺伊曼瓶颈:

Surely there must be a less primitive way of making big changes in the store than by pushing vast numbers of words back and forth through the von Neumann bottleneck. Not only is this tube a literal bottleneck for the data traffic of a problem, but, more importantly, it is an intellectual bottleneck that has kept us tied to word-at-a-time thinking instead of encouraging us to think in terms of the larger conceptual units of the task at hand. Thus programming is basically planning and detailing the enormous traffic of words through the von Neumann bottleneck, and much of that traffic concerns not significant data itself, but where to find it.2

鉴于此,我们在CPU芯片内部开辟了一小部分空间,用来存储与CPU频繁通信的数据,甚至根据数据与CPU通信的频繁程度等因素的不同而存储在不同的区域,这就是 CPU缓存(CPU Cache) 。根据寄存器与CPU核心的“距离”将其分为一级缓存、二级缓存等。

一般而言,缓存等级越小,代表其与CPU核心越近,速度也就越快,由于其在“繁华地段”,空间也就越小,造价亦是越高。

1.3 寄存器

虽然在计算机体系结构中存在有存储器,但是运算器与控制器在运行时依然需要将数据临时存储。在CPU内部有各种用于存储数据的空间,专门用于存储数据或指令,即寄存器(Register)。

一般而言,计算机存储部件的速度为:寄存器(可以CPU同频率工作)> 一级缓存 > 二级缓存 > … > 内存

2. 计算机软件

官方一点讲,我们所谓的“计算机”指的是计算机硬件与软件,纯计算机硬件只能根据自然现象做无意义的响应。这就需要我们制定相应的逻辑去干预。而如何制定合理逻辑,如何让冰冷的机器理解,以及如何让其高效准确地执行,这就是软件需要考虑的问题。

2.1 二进制

由于计算机是由 电能驱动 ,那么如何让计算机能理解我们的信息(数据)并处理就是要面对的首要问题。

很容易联想到的一个方案就是用电流或电压的大小来表示数据:1V表示1,2V表示2……那么要表示从地球到月球有多少米呢?这种方式有点耗能量,也有点危险……

换一个思路,我们使用一个开关来控制“有电”或者“没有电”,有电表示1,没有电表示0。那么在存储数据时,可以抽象地理解为通过该存储单元是否有电(1或0)来表示信息。

由此,可以使用两个状态来表示各种数据(只要空间够大)。比如现在有8个存储单位,分别都可以表示0或1,那么这些单位组合起来一共可以表示 28 种不同的状态。每一个存储单位叫做位(bit),这8位空间就叫做一个字节(Byte)

按照计数基本方法,我们将使用2个数字来表示各种数据,这就是 二进制(Binary),类比十进制,二进制逢二进一,那么十进制的2,用二进制将表示为10。

以下为十进制数字与二进制数字的简要对照,供初学者理解3

十进制 32 16 10 9 8 7 6 5 4 3 2 1 0
二进制 100000 10000 1010 1001 1000 111 110 101 100 11 10 1 0

2.2 程序

机器语言

由于计算机底层只能理解二进制数,故欲传达指令,也是使用由01组合的数字为媒介,这就需要机器能理解指令。计算机芯片在诞生之时,该能力已经由生产厂商赋予。开发人员按照厂商所给的“语法”进行开发,这就是机器语言(Machine Language)。

随着社会的发展,计算机要解决的问题越来越复杂,是用该方式开发的弊端暴露无遗:机器语言人类太难直观理解,开发、调试、修改困难。

汇编语言

为了解决以上问题,厂商将该“语法”进行了升级,用简单的单词缩写来代替二进制代码,即汇编语言(Assembly Language),如此一来大大减小了开发难度(相对而言)。

汇编语言虽然提高了人类对于开发语言的理解,但是依然非常底层(即逻辑接近机器),开发程序需要学习大量计算机理论,门槛较高,同时依然面对与机器语言相同的问题,不易于维护。

高级语言

高级语言是以人类的日常语言为基础的一种编程语言,使用一般人易于接受的文字来表示,有较高的可读性,以方便对计算机认知较浅的人亦可以大概明白其内容。

高级语言与计算机的硬件结构及指令系统无关,它有更强的表达能力,可方便地表示数据的运算和程序的控制结构,能更好的描述各种算法,而且容易学习掌握。但高级语言编译生成的程序代码一般比用汇编程序语言设计的程序代码要长,执行的速度也慢。所以汇编语言适合编写一些对速度和代码长度要求高的程序和直接控制硬件的程序。这里所谓的“高级”的意义是距离人类逻辑较近,即更易理解。

2.3 操作系统

由于不同的硬件厂商生产的产品不同,所给的语法(即指令集(ISA))不同,使用汇编开发的程序移植性很差,而高级语言最终也需要转为机器语言才可让硬件理解,并且即使是同一个机器上的不同程序,也会有大量的相同逻辑,来负责硬件资源调度等基本工作,以提供一个可能执行业务计算的前提。由此就迫切需要一个通用的代码,负责与底层硬件交互,为应用程序提供运行环境。

这就是现代操作系统(Operating System)的主要任务之一。它弥合了底层硬件的差异,对上层提供一致的接口与规范。比如如何让读取数据,如何驱动声卡发声等。程序可以直接调用该库进行工作,即系统调用

由于系统调用虽然提供了相关能力,但是依然太过于底层,仅仅使用系统调用的方式开发应用程序太过于困难,对于程序员的学习要求也过高。故一个完整的系统一般会在用户空间将系统调用再次封装,使之成为有实际作用的接口,封装后的接口通常以C库的方式对外提供。即API(Application Programming Interface),程序员可使用这些库调用进行开发,也可以直接使用系统调用,实现更能灵活的代码操作。

操作系统的另一个任务就是要协调各个应用。计算机底层实质上是一堆逻辑电路的组合,故在某一刻只能执行一项运算,随着硬件运算能力的提升,这种机制对于计算能力的浪费是巨大的。这就需要程序有一个约定好的“规则”,以确定如何使用硬件资源。

操作系统可以作为“监控者”,合理分配运算与存储资源给各个应用程序。同时,其还提供其他能力,如,将通用的功能封装为接口,以供程序调用。

目前主流的操作系统有:

  • Windows,个人电脑主流操作系统,VMS内核
  • MacOS,苹果公司生产的Mac电脑操作系统,FreeBSD内核
  • Linux,服务器或商业主流操作系统,拥有众多发行版
  • Android,移动终端主流操作系统,实质上是运行在Linux之上的Java虚拟机
  • IOS,苹果公司生产的移动终端操作系统,流畅高效

二、Linux基础介绍

1. Linux历史简介

上文提到的操作系统已经是较为成熟的产品,而在电子计算机刚诞生之初并非如此。当时的计算机体积巨大、耗电惊人,当时人们使用穿孔纸带对其输入数据与指令:
穿孔纸带

无疑,这种方式效率低下。故1964年,由美国通用电气(GE)、国电话电报公司(AT&T)的贝尔实验室(Bell-Labs)以及麻省理工大学(MIT)的人工智能实验室组成一个团队,旨在研制一个运行在大型机上的高效的多任务处理系统,Multics(MULTiplexed Information and Computing System) 就此诞生!

Multics项目是成功的,在达到了最初设定的目标后,到了七十年代,Bell-Labs与GE相继退出,他们的计算机科学家也将无权再继续使用Multics。这致使Bell-Labs的一位科学家Ken Thompson开发的一款基于Multics系统的游戏 Space Travel 无法运行,Ken随后使用DEC公司的PDP-7主机(当时DEC公司的PDP系列已经到了PDP-11),按照自己对于Multics的理解,重写了一个能运行自己游戏的平台来运行自己的游戏。

在他向同事们展示Space Travel时,其同事们将目光瞄向了这个底层系统,该系统遂风靡贝尔实验室。由于该系统设计之初仅仅为了支持该游戏的运行,相对于Multics,大家将该系统戏谑地称为Unics ,后来更名为Unix

而Unix此时依然是使用汇编开发的,移植起来较为繁琐。Ken好友Dennis Ritchie希望使用高级语言重新开发该系统,遂将当时的B语言进行改进,引入了静态变量、加入了指针等概念,即成为了现代C语言的前身。并使用该语言重新了Unix。

1974年,二位公开讲述了他们的Unix,将论文刊登于美国计算机通讯杂志。由于当时的法律,AT&T不能销售Unix,二人须无偿对外提供,Unix迅速风靡各高校以及研究机构。

其中包括加州大学伯克利分校,该校学生Bill Joy成立了CSRG(Computer Systems Research Group),而Ken在休假期间刚好去了该校任教,CSRG成为了Unix研究的领头羊4

是时,网络兴起,DARPA将TCP/IP协议栈的研究交给CSRG,CSRG将研究成果整合到了系统中,即BSD(Berkeley System Distribution)。

在这段时间,各地纷纷出现了一些公司,他们包装发行Unix、编译器等。如SCO、Microsoft(微软),Microsoft当年以销售Basic编译器为生,并且也包装发售Unix,称为Xenix。

上世纪八十年代初,IBM Compaq开始生产PC,由于当时Intel的80x86芯片性能很差,而当时的Unix程序员不愿将Unix移植到PC兼容机上。加之Bell-Labs若离了AT&T后,迅速将Unix商业化,各个高校与研究机构也无法再免费使用Unix(当时的操作系统很昂贵)。

鉴于此种状况,又有牛人开始自己研发,美国一位教授开发了CP/M系统,以及另一位默默无闻的程序员开发的QDOS(Quick and Dirty Operating System)。QDOS后来被比尔盖茨买下,修改后命名为DOS(Disk Operating System)。并且通过一种新的卖使用许可证的方式销售该系统的使用权,大获成功。

另一边,Apple公司的Jobs在Xerox的PARK实验室发现了鼠标与图形操作系统,并将其应用在Apple 2上。其友商Microsoft不久也获取到了该技术的拷贝,Windows就此诞生!但是内核依然是DOS。

Unix阵营这边,贝尔实验室与CSRG的一场长达数年之久的争论接近尾声。Bill Joy成立了Sun Microsystem公司,为世界贡献了Java语言、Solaris系统、Spark等,后来被Oracle收购。

而当时的DEC公司被COMPAQ收购,其VMS系统团队加入了微软,改进Windows,内核更新为VMS。

上文提到,由于Unix的商业化,众多高校以及科研机构无法免费使用Unix。麻省理工学院的一位教授Stallman对此大为不满,他认为认为程序是全人类的,倡导软件应公开使用,成立GNU(GNU is Not Unix)组织,颁布了GPL(General Public License)协定5

GNU组织贡献了众多优秀的软件,如EMACS、gcc、vi等。有意思的是,这些软件只能运行在Unix系统上!

这里又是一位牛人,荷兰一大学教授Andrew仿照Unix开发出了Minix(据说只有4000多行代码),并用它的欧盟各地教学。然而Minix的底层驱动用汇编开发,无法在学生的电脑上使用,一些学生在自己的电脑上开发多中平台的驱动,但Andrew不同意将这些驱动融合在Minix中。

最后一位压轴出场的就是LInux之父:Linus Torvalds!1991年8月,还在赫尔辛基大学上学的的Linus写了一个小系统Linux,并宣布其遵循GPL协定,任何人可以更改系统。加之其满足了GUN组织迫切需要一款操作系统的需求。
Linus Torvalds

此后,世界各地的黑客、程序员等纷纷参与其中,不断完善Linux,Linux就此迅速成长。如今,Linux内核已然相当健壮。

2. 开源协定

软件的开源(Open Source) 指的是在将源代码公开,但这并不意味着它没有版权,为了开源协定的作用之一,就是保护这类软件的版权。这里罗列以下几个常见的开源协定。

GPL

Gnu general Public License,GNU通用公共许可证,规定了用户可以自由查看、修改、传播软件(及源代码),其中一些要求如下

  • 若使用了该协定,且欲使用软件收费,则需要像客户说明该软件遵循GPL,客户可以免费获得,并且需要说明收费的理由
  • 若软件用引用了任何遵循GPL的代码,则该软件也需要遵循GPL

目前的最新版为GPL v3.0

LGPL

鉴于GPL软件的严苛,使得其有一种“传染性”,从某种程度上限制了自由软件的传播。LGPL为Lesser GPL,它较GPL稍显宽松,大致区别在于

  • 可以通过类库引用的方式使用LGPL代码,而软件无需开放源代码
  • 若修改了LGPL的代码,则涉及到的代码以及衍生代码都需要遵循LGPL

因此,LGPL适合作为第三方的类库被使用

目前的最新版本为LGPL v3.0

BSD License6

BSD协议较以上二者,给了开发者极大的自由,要求为

  • 使用了遵循BSD协定的软件后,若发布的软件为源代码,则在源代码中必须带有原来代码中的BSD协议
  • 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议
  • 不能使用原程序作者或组织的名字来对软件进行宣传

严格来讲,BSD许可证是由加州大学伯克利分校(UCB)开发的一类非常简单且非常自由的计算机软件许可证。这里讲的是Original BSD license

Apache License

该协定与BSD类似,依然较为宽松

  • 若修改了遵循该协定的代码,则需要再被修改的文件中进行说明
  • 在衍生出的代码中需要带有原来代码中的协议,商标,专利声明等,以及原作者规定需要包含的其他说明
  • 若发布的产品中包含Notice文件,则在Notice文件中需要带有Apache Licence,同时也可以在Notice中增加自己的许可,但不可以与Apache Licence冲突
  • 需要给代码的用户一份Apache Licence

目前的最新版为Apache License v2.0

下图说明了各协定间的区别,以及如何选择7
choosing_opensource_license

3. Linux发行版

Linux与其他应用(如上文提到的gcc、vi等)是使用高级语言开发(Linux源代码中也混合有低级语言),而程序的运行必须转换为二进制格式,对于非专业人员而言,使用难度很大。

再则,Linux内核不提供有生产力的功能,无法直接使用,而独立的应用程序需要依赖该平台。如此就有一些组织或商业公司,将Linux与众多应用程序整合编译为二进制程序,使大家可以直接安装使用。这就是Linux发行版(Distribution)。

Linux有众多发行版(数百个),其中比较流行的有:

  • RHEL,RedHat Enterprise Linux,红帽(RedHat)公司发行的商业Linux
  • CentOS,Community ENTerprise OS,社区企业操作系统,兼容RHEL,现已被Redhat收购
  • SUSE,slackware二次发行版,属于Novell旗下的业务,OpenSUSE是它的二次发行版,有企业版SLES(SUSE Linux Enterprise Server)
  • Ubuntu,debian的二次发行版,拥有华丽的界面,在个人设备上也很流行,其二次发行版Mint也以美观著称

三、Linux的获取

这里所说的Linux指的是Linux发行版。在国内有众多发行版镜像提供的站点,如:

笔者将使用 CentOS 7 进行学习与测试,以阿里云为例,找到CentOS/7位置,此处将指向当前最新稳定的CentOS 7版本,进入isos/x86_64/


CentOS7镜像下载

这里对图上所列版本做大致说明:

  • DVD版本包含常用的软件包
  • Everything版本包含了所需的几乎所有软件包
  • Live版本可直接运行在移动介质之上
  • Minimal版本只包含了最基础的软件,体积较小

建议初学者下载Everything版本,如此,在安装之后可省去大量的“麻烦”(如所需要的软件没有安装,而自己此时也无从下手)。

另外,LInux Kernel的站点为:https://www.kernel.org

四、基础概念说明

作为学习使用,我们一般将采用将Linux安装在虚拟机的方式进行。关于如何在虚拟机安装Linux,这里不做赘述。以下将通俗介绍一点基本的计算机概念,可能不甚严谨,但是帮助初学者理解已然足矣。

1. Shell

之前有提到,计算机有五大结构,人们通过I/O设备与计算机进行交互,那么通过设备发送的信息是如何传递到计算机内部,进而继续执行的呢?而使用者又是如何知道,何时应该发送何种信息,以及计算机正处于何种状态呢?

很显然,我们通过输出设备获取信息,而该信息则由专门的一类程序负责,即Shell。Shell意为“壳”,是指“为使用者提供操作界面”的软件,同时也接收用户命令,然后调用相应的应用程序。是人机交互的联结者。

Shell大体上分为两类:

  • CLI:Command Line Interface,命令行接口
  • GUI:Graphic User Interface,图形用户接口

CLI顾名思义,界面只有文字,微软的DOS系统、Windows中的命令提示符、PowerShell,Linux中的bash,csh,zsh等

GUI之前也曾提到,由施乐研发,与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受,学习成本也较低。如Windows的桌面,Linux的KDE、GNome等。

2.程序与进程

简单来讲,程序即存储在某介质之上的二进制文件,而进程则是正在运行的占用硬件资源的活动,或者说是正在运行的程序的实例。上文提到的bash、KDE等,都是如此。

那么问题来了,计算机内存在断电后无法保存数据,而计算机在启动时将运行OS,则需要通过外存将存储在其中的程序加载到内存,进而由CPU执行。而“将存储在其中的程序加载”这个指令又是如何执行的呢?

这似乎是一个无解的问题,不过明显地,该问题已经解决:在计算机内部,有一个专门存储这段指令的芯片,且数据可持久保存,在机器加电后,将由硬件逻辑将这段代码加载,进而加载后续的其他进程。

3. 终端

终端Terminal),是一台计算机或者计算机系统,用来让用户输入数据,及显示其计算结果的机器。终端有些是全电子的,也有些是机电的。其又名终端机,它与一部独立的计算机不同。从这个角度而言,计算机可以理解为主机 + 终端

早期的计算机在需要多人操作时,每个用户都要有一个显示器、一个键盘。而在现代Linux系统中,以CentOS7为例,默认将打开6个虚拟终端(Virtual Terminal),按Ctrl+Alt+Fn(F2~F7)切换,也可按Ctrl+Alt+F7启动图形终端(需要事先安装)。

Linux系统支持一下终端类型:

  • 串行终端,设备文件为:/dev/ttyS#(#为数字)
  • 物理终端,即控制台(Console),设备文件为:/dev/console
  • 虚拟终端,设备文件为:/dev/tty#(#为数字)
  • 伪终端,即模拟终端,远程连接或图形界面打开的命令接口,设备文件为:/dev/pts/#(#为数字)

4. CPU架构

计算机的CPU,即中央处理单元在工作时都需要加载到一些命令,而命令是按照相关的标准,将程序源代码在被执行前所翻译出的机器能识别的语言,也叫机器语言,这种翻译过程就是编译(Compile),而翻译时运用的规则叫做指令集(ISA)。最常见的就是RISC(Reduced Instruction Set Computer,精简指令集计算机),以ARM架构为代表,和CISC(Complex Instruction Set Computer,复杂指令集计算机),以x86架构为代表。

而基于某种指令集的具体实现是有多种方式的,这些不同的实现方式基于某一种指令集规范,我们称之为Microarchitecture(微架构)。以英特尔的PC平台为例,早先奔腾系列产品使用的是P5或P6微架构,到后来第五代酷睿系列使用的Haswell,到如今市场上酷睿使用的Coffee Lake,都是复杂指令集的不同实现。

初次之外,还有以下CPU架构:

  • ARM
    Advanced RISC Machine,高级精简指令集机器,该CPU以节能与高效著称。由英国ARM公司设计,这个公司很神奇,他们几乎不生产CPU,只是向外输出技术,是全球领先的半导体知识产权 (IP) 提供商。
  • x86,x64

    x86泛指一系列基于Intel 8086且向后兼容的中央处理器指令集架构。Intel在早期以80x86这样的数字格式来命名处理器,包括Intel 8086、80186、80286、80386以及80486,由于以“86”作为结尾,因此其架构被称为“x86”。

    x86的32位架构一般又被称作IA-32(Intel Architecture, 32-bit),其64位架构由AMD率先推出,并被称为“AMD64”。之后也被Intel采用,被其称为“Intel 64”。一般也被称作“x86-64”、“x64”。8

  • Itanium
    安腾,Intel收购HP的业务,64位架构,与x86,x64不兼容。
  • Alpha
    由DEC公司研发,也叫做Alpha AXP,早起被用户DEC公司生产的设备中,后来被Compaq收购,后HP收购Compaq,继续研发Alpha。
  • Power
    由IBM设计,属于RISC,全称为“Performance Optimization With Enhanced RISC”,性能强劲,价格同样强劲。
  • PowerPC
    Performance Optimization With Enhanced RISC – Performance Computing,简称为PPC。由Apple、IBM、Motorola组成的AIM联盟所发展出的微处理器架构,早期用于苹果的CPU。
  • MIPS

    MIPS架构(英语:MIPS architecture,为Microprocessor without Interlocked Pipeline Stages的缩写,亦为Millions of Instructions Per Second的头字语),是一种采取精简指令集(RISC)的处理器架构,1981年出现,由MIPS科技公司开发并授权,广泛被使用在许多电子产品、网络设备、个人娱乐设备与商业设备上。最早的MIPS架构是32位,最新的版本已经变成64位。9

五、Linux基础概念

1. Linux哲学思想

Linux系统在设计之时,使用了很有前瞻性的组织机制,如今,这些机制已经被广泛引用,甚至已经上升到了哲学高度:

  • 由目的单一的小程序组成
    Linux的每一个程序功能都比较单一10,一来可以专注于一件事,提升效率,二来可以减少Bug
  • 组合多个程序完成复杂任务
    我们可以使用管道、重定向以及脚本等组个多个程序完成较为复杂的功能
  • 一切皆文件
    除了我们用到的数据、程序是以文件的形式展示外,硬件设备、套接字、系统运行参数等都可以以文件形式展示,通过查看或修改文件以达到管理设备、进程间通信以及配置系统运行特性等目的
  • 尽量避免捕捉用户接口
    Linux系统大量应用在Server领域,在系统运行过程中,系统本身很少与操作者进行交互,继承此种思路,没有消息就是最好的消息
  • 配置文件保存为纯文本格式
    配置文件主要用于调整程序的运行特性或方式,使用文本格式保存,可以极大促进其传播
  • 提供机制,而非策略
    这一点与“授人以渔,而非授人以鱼”有着异曲同工个之妙,即提供提供大体规则方向,具体实施方法均由用户(或开发者)的理解制定,这也是Linux会有如此多的发行版的原因之一!

2. Linux Kernel功能

Kernel,即核心,Linux的Kernel就是Linux操作系统运行的核心。事实上,它并不为用户直接提供任何有生产力的功能,而是为了系统的基本运行提供保障。就如我们心脏的跳动,并我们帮我们完成任何学习与工作任务,但是却必不可少。

Kernel提供最底层、最通用的能力:

  • 分配系统资源,即将硬件提供的计算能虚拟化为系统调用,以及对内存的管理
  • 程序管理,程序的启动、终止、切换、回收等工作
  • 硬件驱动,提供硬件与软件的基本接口
  • 通用功能,如网络、文件系统等
  • 安全功能,如SELinux,解密解密算法等

3. 命令提示符

启动系统,登录后11会显示如下信息:

[root@localhost ~]#

这段信息叫做 命令提示符(Prompt),用于提示用户可在此提示符后键入命令。一下对其各部分做以说明:

组件 说明
[ root@localhost ~] # 命令提示符大体分为两部分,[]与其中的部分以及后面的提示符
[ root @localhost ~]# 当前登录用户,这里为root
[root @ localhost ~]# 用于分隔用户名与主机名,这里为@
[root@localhost ~]# 本地主机域名,这里为localhost
[root@localhost ~]# 当前的工作目录(Working Directory)基名(Base Name),这里为用户自己的家目录,使用“~”表示
[root@localhost ~] # 表示当前用户的权限,有两种,管理员为**#,普通用户为$**

关于该提示符的样式,可在相关文件里配置,后续会有详细说明。

4. Linux命令

一般地,用户发起一个命令,即为请求内核将某个二进制程序运行为一个进程,命令本身是一个可执行的程序文件12,可能会调用共享库文件。

由于需要让CPU(或内核)理解并执行命令,故命令必须遵循特定格式规范,如Windows系统的.exe文件、.msi文件,Linux系统中的可执行文件格式为ELF(Executable and Linkable Format)

这里有一类独特的程序,即上文提到的Shell程序,它专门负责解析用户的指令,是介于人类与计算机的接口。解析完成后,启动相应的程序。如bash,以后的学习中若不做特殊说明,shell程序均指bash。

由于其特殊性,在shell程序内部,内置了一些基本的命令,这类命令称之为内建命令(builtin),使用不同的内建命令,执行的即为shell程序的不同功能(或代码段)。

而对应地,另一类就是外部命令,一般程序文件名即为命令名。

可以使用 type命令查看一个命令相关信息,如:

[root@localhost ~]# type cd
cd is a shell builtin
[root@localhost ~]# type vim
vim is /usr/bin/vim

Linux命令的一般格式

Linux命令的一般格式为:

# COMMAND OPTIONS... ARGUMENTS...

COMMAND:命令

OPTIONS:命令的参数,用于修改命令的执行方式,若有多个中间须以空格隔开;有短选项与长选项之分:

  • 短选项:-CHAR,多个短选项可以组合使用,如-a -b可写为-ab
  • 长选项:-WORD,通常不能组合使用
    另外,有些选项也需要带有参数,即选项参数,这些参数可能不必带“-”

ARGUMENTS:命令参数,即命令的作用对象,有的命令可以带多个参数,各参数之间需要使用使用空格分隔。

六、FHS

0. 文件系统概念

计算机实质上就是处理数据的设备,这些数据在存储介质中是以文件(File)的形式存在的,而具体该如何保存,以及如何对硬件进行逻辑抽象管理,使其可以保存,就是文件系统的功能之一。

计算机的文件系统是一种存储和组织计算机数据的方法,它使得对其访问和查找变得容易,文件系统使用文件和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,用户使用文件系统来保存数据不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个文件的所属目录和文件名。在写入新数据之前,用户不必关心硬盘上的那个块地址没有被使用,硬盘上的存储空间管理(分配和释放)功能由文件系统自动完成,用户只需要记住数据被写入到了哪个文件中。

广义角度来讲,Linux系统是有底层的Kernel与上层Application组成。其在计算机启动之前也是以文件的形式存在于外存中,而这些文件保存在外存(以下称为磁盘)的何处位置,Linux的众多发行组织均可以自定义。如此对于用户的学习和使用而言是极为不便的,亦不利于其传播。鉴于此,Linux Foundation(Linux基金会)定义了Linux发行版中,文件所应该遵从的组织方式,即FHS(Filesystem Hierarchy Standard,文件系统层级标准) 13

1. 根文件系统

该规范说明了系统上应该存在哪些目录,以及不同文件所应该保存的位置,以下为简要说明

目录 说明
/bin 所有用户可用的基本命令程序文件
/boot 引导加载器必须用到的各静态文件,如kernel、ramfs(initrd),以及grub(bootloader)等
/dev 设备文件与特殊文件
/etc 系统程序的静态配置文件
/home 普通的家目录的集中位置;一般每个普通用户的家目录默认为此目录下与用户名同名的子目录
/lib 为系统启动或根文件系统上的应用程序(/bin,/sbin等)提供共享库,以及为内核提供内核模块
/lib64 特定字长系统上的库文件,如64位系统上为/lib64
/media 挂载点目录,通常用来挂载移动设备
/mnt 挂载点目录,通常挂载额外的临时文件系统
/opt, /options 附加应用程序的安装位置,可选
/proc 虚拟文件系统,用于为内核及进程存储其相关信息
/root 管理员的家目录,可选
/run 存放动态的,不持久的应用程序运行数据
/sbin 供管理员使用的工具程序
/srv 系统上运行的服务用到的数据
/sys sysfs虚拟文件系统提供了一种比proc更为理想的访问内核数据的途径;其主要作用在于为管理Linux设备提供一种统一模型的的接口
/tmp 临时文件
/usr 全局共享的只读数据路径
/var 频繁发生变化的文件
/misc 备用目录,可选
/selinux SELinux(Security Enhanced Linux)相关的安全策略等信息的存储位置
[root@localhost ~]# ls /
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr

2. /usr目录层级

usr意为universal shared read-only file,全局共享只读文件,即该目录可以在所有遵循FHS的主机间共享(只读)

目录 说明
/usr/include C程序头文件
/usr/bin 普通用户命令
/usr/sbin 供管理员使用的命令
/usr/lib 库文件
/usr/lib<qual> 特定字长系统上的库文件,如64位系统上为/usr/lib64
/usr/share 命令手册也和自带文档等架构特有的文件的存储位置,例如doc, man等
/usr/X11R6 X-Window程序的安装位置(可选)
/usr/src 程序源码文件的存储位置
/usr/local 第三方软件的安装路径,也是一个独立层级
/usr/games 游戏或教育程序

/usr/local:local目录层级

该目录也是一个独立的层级,其中有bin,sbin等目录,如下内容引用自 https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLOCALLOCALHIERARCHY

The /usr/local hierarchy is for use by the system administrator when installing software locally. It needs to be safe from being overwritten when the system software is updated. It may be used for programs and data that are shareable amongst a group of hosts, but not found in /usr.
Locally installed software must be placed within /usr/local rather than /usr unless it is being installed to replace or upgrade software in /usr.

Directory Description
bin Local binaries
etc Host-specific system configuration for local binaries
games Local game binaries
include Local C header files
lib Local libraries
man Local online manuals
sbin Local system binaries
share Local architecture-independent hierarchy
src Local source code

3. /var目录层级

/var contains variable data files. This includes spool directories and files, administrative and logging data, and transient and temporary files.
Some portions of /var are not shareable between different systems. For instance, /var/log, /var/lock, and /var/run. Other portions may be shared, notably /var/mail, /var/cache/man, /var/cache/fonts, and /var/spool/news.
/var is specified here in order to make it possible to mount /usr read-only. Everything that once went into /usr that is written to during system operation (as opposed to installation and software maintenance) must be in /var.
If /var cannot be made a separate partition, it is often preferable to move /var out of the root partition and into the /usr partition. (This is sometimes done to reduce the size of the root partition or when space runs low in the root partition.) However, /var must not be linked to /usr because this makes separation of /usr and /var more difficult and is likely to create a naming conflict. Instead, link /var to /usr/var.
Applications must generally not add directories to the top level of /var. Such directories should only be added if they have some system-wide implication, and in consultation with the FHS mailing list.14

目录 说明
/var/log 日志目录及文件
/var/lock 锁文件
/var/run 运行中的进程相关的数据,通常用于存放进程的PID文件
/var/cache 应用程序缓存数据目录
/var/lib 应用程序状态信息数据
/var/local 专用于为/usr/local下的应用程序存储可变数据
/var/opt 专用于为/opt下的应用程序存储可变数据
/var/spool 应用程序数据池
/vat/tmp 保存系统两次重启之间产生的临时数据

4. /sys目录内容

/sys 下的子目录 所包含的内容
/sys/devices 这是内核对系统中所有设备的分层次表达模型,也是 /sys 文件系统管理设备的最重要的目录结构,下文会对它的内部结构作进一步分析;
/sys/dev 这个目录下维护一个按字符设备和块设备的主次号码(major:minor)链接到真实的设备(/sys/devices下)的符号链接文件,它是在内核 2.6.26 首次引入;
/sys/bus 这是内核设备按总线类型分层放置的目录结构, devices 中的所有设备都是连接于某种总线之下,在这里的每一种具体总线之下可以找到每一个具体设备的符号链接,它也是构成 Linux 统一设备模型的一部分;
/sys/class 这是按照设备功能分类的设备模型,如系统所有输入设备都会出现在 /sys/class/input 之下,而不论它们是以何种总线连接到系统。它也是构成 Linux 统一设备模型的一部分;
/sys/block 这里是系统中当前所有的块设备所在,按照功能来说放置在 /sys/class 之下会更合适,但只是由于历史遗留因素而一直存在于 /sys/block, 但从 2.6.22 开始就已标记为过时,只有在打开了 CONFIG_SYSFS_DEPRECATED 配置下编译才会有这个目录的存在,并且在 2.6.26 内核中已正式移到 /sys/class/block, 旧的接口 /sys/block 为了向后兼容保留存在,但其中的内容已经变为指向它们在 /sys/devices/ 中真实设备的符号链接文件;
/sys/firmware 这里是系统加载固件机制的对用户空间的接口,关于固件有专用于固件加载的一套API,在附录 LDD3 一书中有关于内核支持固件加载机制的更详细的介绍;
/sys/fs 这里按照设计是用于描述系统中所有文件系统,包括文件系统本身和按文件系统分类存放的已挂载点,但目前只有 fuse,gfs2 等少数文件系统支持 sysfs 接口,一些传统的虚拟文件系统(VFS)层次控制参数仍然在 sysctl (/proc/sys/fs) 接口中中;
/sys/kernel 这里是内核所有可调整参数的位置,目前只有 uevent_helper, kexec_loaded, mm, 和新式的 slab 分配器等几项较新的设计在使用它,其它内核可调整参数仍然位于 sysctl (/proc/sys/kernel) 接口中 ;
/sys/module 这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编译为外部模块(ko文件),都可能会出现在 /sys/module 中:
● 编译为外部模块(ko文件)在加载后会出现对应的 /sys/module/<module_name>/, 并且在这个目录下会出现一些属性文件和属性目录来表示此外部模块的一些信息,如版本号、加载状态、所提供的驱动程序等;
● 编译为内联方式的模块则只在当它有非0属性的模块参数时会出现对应的 /sys/module/<module_name>, 这些模块的可用参数会出现在 /sys/modules//parameters/<param_name> 中,
●● 如 /sys/module/printk/parameters/time 这个可读写参数控制着内联模块 printk 在打印内核消息时是否加上时间前缀;
●● 所有内联模块的参数也可以由 “<module_name>.<param_name>=” 的形式写在内核启动参数上,如启动内核时加上参数 “printk.time=1” 与 向 “/sys/module/printk/parameters/time” 写入1的效果相同;
● 没有非0属性参数的内联模块不会出现于此。
/sys/power 这里是系统中电源选项,这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机、重启等。
/sys/slab (对应 2.6.23 内核,在 2.6.24 以后移至 /sys/kernel/slab) 从2.6.23 开始可以选择 SLAB 内存分配器的实现,并且新的 SLUB(Unqueued Slab Allocator)被设置为缺省值;如果编译了此选项,在 /sys 下就会出现 /sys/slab ,里面有每一个 kmem_cache 结构体的可调整参数。对应于旧的 SLAB 内存分配器下的 /proc/slabinfo 动态调整接口,新式的 /sys/kernel/slab/<slab_name> 接口中的各项信息和可调整项显得更为清晰。15

5. 其他说明

设备文件

  • 块设备(b)
  • 字符设备(c)
  • 设备号:对设备文件使用ls -l查看时,显示文件大小的位置显示为2个数字,即主设备号(major number)与次设备号(minor number)
    • 主设备号,用于标识设备类型,进而确定要加载的驱动程序
    • 次设备号,用于标识同一类型中的不同的设备;

如:

[root@localhost ~]# ls -l /dev
total 0
crw-rw----. 1 root video    10, 175 Dec 28 22:21 agpgart
crw-------. 1 root root     10, 235 Dec 28 22:21 autofs
drwxr-xr-x. 2 root root         180 Dec 28 22:21 block
drwxr-xr-x. 2 root root          80 Dec 28 22:21 bsg
crw-------. 1 root root     10, 234 Dec 28 22:21 btrfs-control
drwxr-xr-x. 3 root root          60 Dec 28 22:21 bus
lrwxrwxrwx. 1 root root           3 Dec 28 22:21 cdrom -> sr0
drwxr-xr-x. 2 root root         100 Dec 28 22:21 centos
drwxr-xr-x. 2 root root        3060 Dec 28 22:21 char
crw-------. 1 root root      5,   1 Dec 28 22:21 console
lrwxrwxrwx. 1 root root          11 Dec 28 22:21 core -> /proc/kcore
drwxr-xr-x. 6 root root         140 Dec 28 22:21 cpu

/etc中常见目录

  • /etc/opt:/opt下程序的配置文件
  • /etc/sysconfig: 系统级别应用配置
  • /etc/init.d: 系统服务脚本
  • /etc/X11:X协议相关配置文件
  • /etc/sgml:SGML相关配置文件
  • /etc/xml:XML相关配置文件

库文件

  • 在/lib与/lib64中保存有共享库文件
  • 静态库:.a文件,直接链接到程序的地址空间中,作为程序的一部分额运行,便于程序单独管理
  • 动态库:.so(shared object)文件,即使有多个程序要使用,在内存中也只有一份
  • libc.so.*:动态链接的C库
  • ld*:运行时链接器/加载器
  • modules:内核模块文件存储目录

Linux上的应用程序的组成部分总结

  • 二进制程序: /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /usr/local/sbin
  • 库文件:/lib, /lib64, /usr/lib, /usr/lib64, /usr/local/lib, usr/local/lib64
  • 配置文件:/etc, /etc/DIRECTORY, /usr/local/etc
  • 帮助文件:/usr/share/man, /usr/share/doc, /usr/local/share/man, /usr/local/share/doc

  1. 此处指的是Linux Kernel ↩︎

  2. 引用自 https://en.wikipedia.org/wiki/Von_Neumann_architecture ↩︎ ↩︎

  3. 详见 https://en.wikipedia.org/wiki/Binary_number ↩︎

  4. 据说CSRG后来由美国DARPA资助,专门致力于改进AT&TUnix操作系统。 ↩︎

  5. 详见下文。 ↩︎

  6. 这个协定其实很有意思,可以看看这里: http://www.linfo.org/bsdlicense.html#disclaimer ↩︎

  7. 图片来源 https://leohacker.files.wordpress.com/2011/05/choosing_opensource_license.png ↩︎

  8. 详见 https://en.wikipedia.org/wiki/X86 ↩︎

  9. 引用自 https://zh.wikipedia.org/wiki/MIPS架构 ↩︎

  10. 那些提供复杂服务解决方案的程序除外 ↩︎

  11. 这里使用root用户登录,仅作为测试学习,在生产环境中,不应该使用该用户登录系统! ↩︎

  12. 也有可能出现多个命令对应一个程序文件的情况,如bash的内建(builtin) 命令。 ↩︎

  13. 目前的最新版为FHS3.0,详见 https://refspecs.linuxfoundation.org/fhs.shtml ↩︎

  14. 引用自 https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#THEVARHIERARCHY ↩︎

  15. 表格内容引用自 https://www.ibm.com/developerworks/cn/linux/l-cn-sysfs/ ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章