树莓派开始,玩转Linux18:完整架构

本文详细介绍了Linux系统的完整架构,包括内核模式与系统调用、库函数、Shell以及用户程序。内核作为单一进程管理计算机资源,系统调用是应用程序与硬件交互的基础。库函数则提供了更高级别的接口,简化了编程工作。Shell作为用户与系统的桥梁,允许用户通过命令行执行程序和编写脚本。用户程序则是系统架构的顶层,包括各种预编译的应用。了解这一层次结构有助于深入理解Linux系统的工作原理。
摘要由CSDN通过智能技术生成

树莓派开始,玩转Linux18:完整架构

Linux系统可以分为内核和应用程序两个主要部分,但如果细分,内核和应用程序之间,还可以有更精细的模块划分。完整的Linux系统架构,如图所示,下面分别来看Linux架构中的不同部分。

在这里插入图片描述
1.内核模式与系统调用:

计算机启动之后,Linux的内核程序启动成为一个单一的内核进程。这个单一进程将执行内核的相关功能。内核进程有权调用所有的计算机资源。当应用程序运行时,内核会分配给该应用程序一定的计算机资源。应用程序与硬件之间的互动,也必须经由内核进行。因此,即使是一个应用程序,它的运作也离不开内核。我们把内核程序的活动称为内核模式(Kernel Mode),而把应用程序的活动称为用户模式(UserMode)。

应用程序可以通过特定的接口来调用内核功能。用户单次的内核调用,可以称为一次系统调用(System Call)。接口中的系统调用有大约两百种,每种系统调用都有特定的名称和调用方式。在Shell中输入下面的命令就可以查看Linux下所有的系统调用。

在这里插入图片描述
在Linux最常见的开发语言C中,系统调用都制作成了有特定函数名
的函数。你可以通过:
在这里插入图片描述
来查看系统调用read这一系统调用的说明。命令中的2,对应了系统调用类相关的查询。
命令man定义的几个查询类可以通过下面的命令查看:
在这里插入图片描述
常见的系统调用如下:

· read,文件读取。
· write,文件写入。
· fork,复制当前进程。
· wait,等待某个进程完成。
· chdir,改变工作目录。

每次系统调用,用户程序就触发了内核的特定动作。以bash中的内置函数cd为例。
bash实际上执行的就是进行chdir这个系统调用。系统调用发生后,作为用户进程的bash暂停,操作系统转入内核模式。当内核完成chdir的系统调用后,即更改了进程的工作目录,bash进程将恢复执
行,程序又重回用户模式。

对于用户程序来说,系统调用是内核的最小功能单位。用户程序不可能调用超越系统调用的内核动作。一个系统调用就像是汉字的一个笔画。任何一个汉字都要由基本的笔画构成,没有人可以臆造笔画。通过系统调用这个接口,Linux实现了内核封装,隐藏了底层的复杂性,也提高了上层应用的可移植性。

2.库函数:

系统调用提供的功能非常基础,使用起来很麻烦。一个给变量分配内存空间的简单操作,就需要动用多个系统调用。为了方便,程序员还可以使用上层的库函数(Library Function),来实现特定的"组合拳"。

函数是面向过程语言中复用代码功能的一种方式。所谓的"库"是一个文件,它包含了多个常用函数。在C语言中,我们可以跨文件地调用库中的函数。C语言本身就规定了C标准库(C Standard Library)。之前使用的printf函数,就属于C标准库:
在这里插入图片描述
如果只是使用系统调用来实现上面的程序,那么我们编程的工作量
就会增加:
在这里插入图片描述
在这个程序中,我们需要手动为文本分配内存空间,并计算文本的长度。而在之前的程序中,这些工作都由printf代劳。此外,printf还可以改变文本输出的格式,并且优化输入和输出的效率,这些都是write系统调用所不具备的。

我们可以用man来查阅库函数的帮助文档。库函数的查询类是3:
在这里插入图片描述
除了C标准库,Linux系统中还有很多其他的库,比如POSIX标准库。UNIX操作系统都会安装POSIX标准库。函数malloc就是POSIX标准库中的库函数,这个函数常用于内存分配。目录/lib和/lib64下存放着Linux系统自带的库。用户也可以在目录/usr/lib下安装额外的库。这些库函数把程序员从细节中解救出来,极大提高了编程效率。

3.shell:

系统调用和库函数是为程序员准备的,普通用户使用的都是编译好的应用程序。在所有应用程序中,Shell的地位相当特殊。在历史上,Shell曾经是Linux用户使用计算机的唯一界面。用户必须在Shell中用命令的方式来运行程序。当然,随着图形化桌面的发展,让用户有了一个新的运行程序的界面。但图形化桌面并不能完全取代Shell的地位。很多程序只能通过Shell的方式启动,比如用于下载的wget。

Shell把Linux系统的很多功能开放给用户。对于有编程能力的高级用户来说,他们当然可以通过系统调用、库函数和C语言编程来完整地发挥Linux系统的能力。在另一个极端,大多数应用程序有其专攻的方向,比如文字编辑、收发邮件、显示网页等。一个应用程序只发挥了操作系统很小的一部分能力。Shell介于两者之间,把相对底层的功能用简单而统一的接口呈现给用户,比如用简单的文本符号"|"来使用管道,又如用内置命令cd来改变Shell的工作目录等。对于编程经验有限的普通用户来说,Shell开放出来的系统功能是福音。由于Shell很简单,又容易和其他应用程序互动,它的开放接口也深受资深程序员的喜爱。

我们也已经看到Shell的可编程性。借着这种可编程性,Shell可以充当不同命令之间的"胶水",把功能专一的应用程序组合成功能多样的脚本。此外,脚本还可以预设一连串的操作。用户可以把耗时的手工操作编写成Shell脚本,让Linux系统按照脚本的指挥自动运行。很多Linux计算机就是凭着Shell脚本,在无人工干预的情况下长期工作。

4.用户程序:

整个架构的最上层就是应用程序。我们已经知道,应用程序是二进制的可执行文件。在/bin和/usr/bin中,我们可以看到不少这样的可执行文件。可执行文件还可以出现在文件系统的其他位置。按照惯例,应用程序所在的目录都被命名为bin。这里的bin是指binary,即二进制。

Linux中大多数可执行文件都是由C语言编写的。当然,你还可以用其他的语言来编写程序,如C++和Fortran。C语言写成的程序是可读的文本,必须经过编译才能生成可执行文件。我们可以用gcc命令把C程序直接编译成可执行文件。但在幕后,gcc实际上要做好几件事。它必须对源代码进行一定的文本处理,把人类可读的文本翻译成机器可读的二进制序列,最后还要找到程序依赖的库文件。
编译成功后,就可以用Shell运行应用程序。两种运行程序的方式如下。
· 直接输入程序名,如ls、man、wget。
· 在应用程序所在的目录中用"./可执行文件名"的方式,比如./a.out。

这两种方式的区别在于,前一类的命令包含在Shell的默认路径中。
输入这些命令时,Shell会搜索默认路径,直到找到同名的程序并运行。
默认路径在Shell中保存为一个变量,你可以打印出该默认路径:
在这里插入图片描述
可以看到,/bin包含在PATH变量中。由于ls程序位于/bin中,因此我们可以不加路径地运行该程序。

如果应用程序所在位置在默认路径之外,那么我们就必须切换工作目录,或者使用完整路径,如:
在这里插入图片描述
Linux系统提供了一个多层次的互动平台。从应用程序到Shell,再到库函数和系统调用,用户可以一层层地接近底层。越往底层,用户受到的限制越少,能发挥的功能越丰富。

当然,学习难度也越来越大。对于爱好挑战的计算机爱好者来说,这样的"学习升级"过程也充满了趣味。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值