(2021.08.11 Wed)
- Hardware − Hardware consists of all physical devices attached to the System. For example: Hard disk drive, RAM, Motherboard, CPU etc.
- Kernel − Kernel is the core component for any (Linux) operating system which directly interacts with the hardware.
- Shell − Shell is the interface which takes input from Users and sends instructions to the Kernel, Also takes the output from Kernel and send the result back to output shell.
- Applications − These are the utility programs which runs on Shell. This can be any application like Your web browser, media player, text editor etc.
(2020.11.05 Thur)
Linux系统分为内核(kernel)和应用程序两个部分。若细分,Linux系统从内到外分别是,硬件内核系统调用Shell和库函数应用程序。
Linux系统的创作者写的Linux系统实际上只有内核,他所开源的是内核的代码。
内核的特点
- Linux启动后就一直运行
- 开机后,内核启动后会运行一个初始脚本,调用常用的应用程序
- 有权调配所有的计算机(硬件)资源
- 内核运行之后才会运行应用程序
- 内核管理着应用程序
- 给每个应用程序独立的内存空间和运行时间(即资源),使其可以同时运行
- 内核是应用程序和硬件互动的通道
- 内核程序的活动称为内核模式(kernel mode),应用程序的活动称为用户模式(user mode)
- 提供的函数接口简化了应用程序的开发
内核与应用程序的关系
除了上面提到的内核运行和管理应用程序以及做应用程序和硬件之间的通信通道。不同的应用程序还有不同的权限,以便调用不同级别的内核功能。比如当多个应用程序调用同一个硬件设备(打印机),内核必须决定其优先级,以免出现多个应用程序同时打印在一张纸上的混乱情况。没有任何应用程序可以像内核一样全面掌控计算机资源。
内核和应用程序的区分方式并非Linux独有的。当然也可以设计一个操作系统,允许应用程序直接调用计算机资源,可以省去运行内核程序的开销,应用程序甚至可以达到更高的运行效率。比如很多简单的嵌入式系统,智能手环等等 。
内核提供了一套接口给开发者,使得开发者在无需掌握硬件知识的前提下就可以开发程序。Linux提供的接口可总结为300多个函数接口,常用的几十个。接口的只做是根据POSIX(portable operating system inteface of UNIX)。这样的标准使得Linux应用程序恶意简单修改就可以应用于其他的 UNIX系统。
GNU
GNU系统 包括内核和应用程序。
Linux发行版
厂商在内核和GNU的基础上,开发自己的软件并调整配置,以便更好额进行用户支持,形成发行版。
系统调用system call
应用程序可以通过特定的接口来调用内核功能,用户单词的内核调用,可以成为一次系统调用。
$man 2 syscalls #查看Linux下所有系统调用的指令
$man 2 read #查看read这一系统调用的说明。
$man man #查看man定义的几个查询类
常见的系统调用
- read 文件读取
- write 文件写入
- fork 复制当前进程
- wait 等待某个进程完成
- chdir 改变工作目录
调用的过程
每次系统调用,用户程序就触发了内核的特定动作。以bash中的内置函数cd为例。bash实际上执行的就是进程chdir的系统调用,调用发生后,作为用户进程的bash暂停,操作系统进入内核模式。当内核模式完成chdir的系统调用后,即更改了进程的工作目录,bash进程将恢复执行,程序又重回用户模式。
对用户程序来说,系统调用时内核的最小功能单位。用户程序不可能调用超越系统调用的内核动作。一个系统调用就像汉字的一个笔画。任何一个汉字都要由基本的笔画构成,没有人可以臆造笔画。通过系统调用这个借口,Linux实现了内核封装,隐藏了底层的复杂性,也提高了上层应用的可移植性。
(2020.11.06 Fri)
库函数Library function
系统调用提供的功能非常基础,使用起来很麻烦。一个给变量分配内存空间的简单操作,需要多个系统调用。为了方便,还可以使用上层的库函数Library function。
函数是面向过程语言中复用代码功能的一种方式。库是一个文件,包含了多个常用函数。C语言中,可以跨文件调用库中的函数。C语言本身规定了**C标准库C standard library,比如常用的printf函数。下面是用系统调用实现printf函数的程序,可见工作量的提升。
#include
#include
int main(void) {
const char msg[] = 'hello world';
int length;
length = sizeof(msg) - 1
write(STDOUT_FILENO, msg, length);
return 0;
}
用man指令查阅库函数的帮助文档。库函数的查询类是3:
$man 3 printf
除了C标准库,Linux库中海油其他的库,比如POSIX库,其中包括malloc函数,用于内存分配。目录/lib和/lib64下存放着Linux系统自带的库,用户可在/usr/lib下安装额外的库。
Shell
略
用户程序
应用程序时二进制的可执行文件,在/bin和/usr/bin中。Linux中的大多数可执行文件是C语言编写。C语言写成的程序时可读的文本,需经过编译才能生成可执行文件。可以使用gcc命令把C程序直接编译成可执行文件。编译过程还包含了对源文件的文本处理、人可读文本翻译成机器可读的二进制序列、找到程序以来的库文件。
运行程序的方式(在Shell中)
- 直接输入程序名,如ls、man、wget
- 在程序所在目录中用'./可执行文件名'的方式,比如./a.out
区别在于前一类的命令包含在Shell的默认路径中,输入命令,Shell会搜索默认路径,直到找到同名的程序运行。默认路径在Shell中保存为一个变量,通过下面指令打印出默认路径
$echo $PATH
可看到,/bin包含在PATH变量中。由于ls程序位于/bin中,因此我们可以不加路径的运行该程序。如果应用程序所在位置在默认路径之外,则必须切换工作目录,或使用完整路径
$/home/some/a.out
Reference
1 Vamei,周昕梓著,树莓派开始玩转Linux,电子工业出版社