(一)何为Linux系统?
(Linux是GNU操作系统的内核,将这种操作系统称为GNU/Linux操作系统)
我们通常所说的Linux内核,只是指Linux内核(只是一个内核,并不是完整的操作系统)
内核是操作系统的核心,是一个支撑软件,管理着计算机所有的硬件资源(CPU,I/O,存储资源),并提供上层应用程序环境
从上图;我们就可以看到,应用程序要访问计算机的资源,就必须通过内核,而想陷入内核(内核态),又必须通过系统调用
系统调用:最小的功能单位,是原子操作,不可分,系统调用本身就是一种中断(软中断)
shell也是一种程序,用于执行我们键入的命令,在Linux系统中,最强大的就是终端,命令了(非UI)其实,在Linux的桌面同样是一个运行程序,(Ubuntu的为GHOME)
shell;命令解释器,读取用户输入,然后执行命令 (用户输入:终端 文件:shell脚本)
说白了,计算机就是跑程序
或者可以这样说: 在“真”(硬件) 上运行 “假” (软件)
由系统内核所提供的功能模块说开来!
第一步:
了解OS是如何管理计算机硬件的
(1)下图是一个典型计算机的硬件组成,具体的不做介绍,应该有相关的了解
我们可以了解到一个程序是如何存放的: 磁盘,非易失性
是如何运行的:CPU,解释或执行存储的指令的引擎
是如何与外部交互的: I/O设备,图形适配器,网络适配器(网卡)
(2)
其实说透了操作系统的功能就是为我们的运行应用程序而准备的,核心就是两个:<1>管理硬件的资源 <2> 管理应用程序
于是乎,操作系统有了以下几个抽象
然后,我们就要开始说Linux操作系统的最重要的三个模块了
文件I/O
虚拟内存
进程
第二步:
开始写我们自己的程序
一般而言在LInux系统上写C/C++程序,有这么个过程
VIM(工具)- GCC/G++(编译系统) - a.out(可执行文件)交由shell执行
- Linux程序编译的过程
(看图理解)
补充:
-
这里里要说的是各项做了些什么事情,
预处理器:宏替换,符号解析,去注释,头文件替换
编译器:词法分析,语法分析(分析程序的语法错误)
汇编器:将程序汇编码生成机器码
链接器:链接静态库,当然也要为动态库做一些事情了 -
ELF文件: 也就是我们在上图看到的二进制文件
注意:虽然ELF文件是二进制的,但是又不同于一般的二进制文件,含有机器码之外还有其它信息,如:段加载地址,运行入口地址,数据段等
1)可重定位目标文件
2)可执行目标文件
3)共享目标文件(即动态库)
说到了这里又不得不提一下静态库和动态库了
可以参考一下下面这篇博客
动态库&静态库
动态库:
①链接器拿它和其他可重定位的文件( .o 文件)以及其他 .so 文
件作为输入,经链接处理后,生成另外的可共享的目标文件( . so 文件)或者可执行的目标文件;
②在运行时,动态链接器拿它和一个可执行的目标文件以及另外-些可共享的目标文件
C.so )来一起处理,在 Linux 系统里面创建一个进程映像 。
需要注意:
静态库(.a) & 动态库(.so)的区别
- 由上图可知,静态库在编译的过程就被装载进了ELF;动态库,为运行时载入内存
- 静态库,每一份都有一份拷贝,浪费资源较大; 而动态库,只保留接口
举个例子:(1) 终端shell之后怎么运行程序
当你在 shell 中敲入一个命令要执行时,内核会帮我们创建一个新的进程,它在往这个新进程的进程空间里面加载进可执行程序的代码段和数据段后,也会加载进动态链接器(在Linux里面通常就是 /lib/ld-linux.so 符号链接所指向的那个程序,它本省就是一个动态库)的代码段和数据。
在这之后,内核将控制传递给动态链接库里面的代码。动态连接器接下来负责加载该命令应用程序所需要使用的各种动态库。
加载完毕,动态连接器才将控制传递给应用程序的main函数。如此,你的应用程序才得以运行。(过程链接表(PLT),Global Offset Table(GOT))
第三步:
运行我们所编写的程序:进程
关于进程 & 线程的概念,参见下面这篇博文
LInux(UNIX)关于线程的经典描述:“未分配资源的进程”
理解进程 & 线程的概念后
说一下进程(线程)几个的点:
【1】操作系统调度进程
进程可为: 实时进程 , 普通进程
交互式程序和批处理程序(统称为普通进程),
实时进程: 基于优先级 采用FIFO或者Round Robin的调度策略.
普通进程: 基于优先级 & 公平占有CPU
对于普通进程调度,需要区分交互式和批处理式的不同
根据进程的不同分类Linux采用不同的调度策略.
对于普通进程,则需要区分交互式和批处理式的不同。传统Linux调度器提高交互式应用的优先级,使得它们能更快地被调度。而CFS和RSDL等新的调度器的核心思想是”完全公平”。这个设计理念不仅大大简化了调度器的代码复杂度,还对各种调度需求的提供了更完美的支持.
注意Linux通过将进程和线程调度视为一个,同时包含二者。进程可以看做是单个线程,但是进程可以包含共享一定资源(代码和/或数据)的多个线程。因此进程调度也包含了线程调度的功能.
linux进程的调度算法其实经过了很多次的演变, 但是其演变主要是针对与普通进程的, 因为前面我们提到过根据进程的不同分类Linux采用不同的调度策略.实时进程和普通进程采用了不同的调度策略, 更一般的普通进程还需要启发式的识别批处理进程和交互式进程.
【2】进程之间如何同步
(同步是建立在进程之间通信之上的,进程通过通信来实现同步)
【3】进程之间通信方式
管道pipe
命名管道FIFO
【4】线程同步
第四步:
加载到内存中运行的程序:虚拟内存
上来又是一张图:
不得不提的几个OS概念
-
中断
-
关于OS操作系统各类调度算法总结:
参见下文:
调度算法
关于操作系统中可能会令我们困惑的一些术语:
-
任务
任务: 任务(task)是最抽象的,是一个一般性的术语,指由软件完成的一个活动。一个任务既可以是一个进程,也可以是一个线程。简而言之,它指的是一系列共同达到某一目的的操作。例如,读取数据并将数据放入内存中。这个任务可以作为一个进程来实现,也可以作为一个线程(或作为一个中断任务)来实现。 -
并发 & 并行
并发:宏观意义上的同时运行
并行:严格意义上的,如多核CPU
-
虚拟内存实现
请求分页式
请求分段式
请求段页式 -
同步和异步 & 阻塞和非阻塞