3.1 程序的组成与执行过程
3.1.1 三种编程接口
在前面几章我们已经粗略的说过,面向计算机通常有三种编程接口,分别是:
a) 硬件规格
b) 系统调用
c) 库调用
每个CPU的生产厂商在生产一个计算芯片时,这个芯片本身有其内置的指令集,所以有一部分人在编程时直接面向这些指令集进行,这类编程方式就是面向硬件规格编程。
3.1.2 程序执行过程
前面我们说过,Intel x86系列的CPU,通常由外而内,指令集是分布在4个环上的,环0上的是特权指令,只能由操作系统执行,环3上的是普通指令,可以由程序执行也可以由操作系统执行。那么程序的执行过程到底怎样?这里举个例子说明一下:
比如我们要计算1+1,计算1+1这条指令并不需要什么特权,程序可以直接执行,但是需要注意的是,要执行1+1需要在内存中取得加数、被加数与加号“+”,而应用程序是无法与内存直接交互的。此时就需要执行系统调用了,第一次系统调用在内存中取出加数,第二次系统调用在内存中取出被加数,第三次系统调用取出加号“+”,剩余的运算才不需要特权指令,才不需要系统调用参与而直接由应用程序执行。
一个程序的运行大多有一部分是普通指令,由内核分配给cpu运行,还有一部分是特权指令,由程序向操作系统发起系统调用,最后由操作系统完成操作并返回结果给程序。一个程序的运行过程大体就是这样,下图是程序运行过程的一张图,可以参考参考。
3.1.3 程序运行模式
如图1所示,因为一个程序的执行大多有两部分组成(特权指令与普通指令),所以一个程序的运行大体分为两个模式,分别是用户模式与内核模式,也称作用户空间(User Space,简称us)和内核空间(System space)
并非系统调用在每个时刻都会发生,因为程序的普通指令是允许直接在CPU上运行的,但特权指令是不允许程序直接在CPU上运行的,必须由操作系统来代理完成。因为现代操作系统一般都是多用户多任务的,CPU只有一个,同一时间只能由一个程序执行,程序1占据了CPU程序2就无法执行,所以为了防止此类现象的发生,才有了内核,由内核来指挥程序运行,而所有的特权指令由操作系统(内核)自己来代理完成。
3.1.4 程序的组成
程序一般由指令+数据组成,其中指令就是cpu内置的指令,它是不可变化的。而数据是由用户提供的,是指令加工的对象,数据是可读写的。
从另一个角度来说,程序是由算法+数据结构组成的。写程序无法是设计数据结构,并设计算法对数据进行加工。算法其实就是CPU的内置指令按照一定的逻辑去运行。
3.2 可移植操作系统规范POSIX
由于直接面向系统调用进行编程过于底层,使编程难度极大增加,于是就有人将这些非常底层与原始的系统调用再次向上抽象了一层,也就是我们所说的库调用。现在的程序员一般大多数情况下是基于库调用和一部分系统调用来研发的,无论是windows还是linux大多数都是基于C语言研发的,所以其库一般都是C库。无论是windows还是linux系统都提供了库,如果两者的库不兼容,会导致在windows上写的程序在linux上没法用,于是国际电子电气工程师协会IEEE(Institute of Electrical and Electronics Engineers)对库的标准定义了一种规范,也就是这节我们要说的可移植操作系统规范POS(Portable Operating System)。有了POS以后,无论在任何平台下写程序,只要程序遵循POS规范,那么其源码在不同平台下是可以兼容的。但是POS这个名字跟约定俗成的Unix、Linux不太像,后来就把POS给改成了POSIX。
事实上,从windows server 2003以后的windows版本和绝大多数的linux、unix版本,其库均是遵循POSIX规范的。
3.3 操作系统程序的接口格式
3.3.1 程序的运行格式
Windows:EXE
Linux:ELF
3.3.2 库格式
Windows:dll(dynamic link library)
Linux:so(share object)
3.4 垃圾回收机制GC(Garbage collection)
3.4.1 C语言特性
C语言允许程序使用指针,可以直接操作内存空间,申请内存和释放内存都是由程序员手动进行的。
malloc():这是一个申请内存的系统调用
free():这是一个释放内存的系统调用
3.4.2 垃圾回收机制背景
让我们来想一个问题,如果A程序运行中free了其他程序的内存空间会怎么样呢?如果程序多次申请内存空间,但是都不释放呢?这些都是不被允许的。因此C语言要求程序员必须精心设计内存的申请和回收,一旦设计有一点点不当,就可能导致程序出错,使程序间互相干扰。缓冲区溢出就是使用这种方式来实现的。
C语言虽然是高级语言,但是其兼具一些低级语言的特性。C语言适用于写操作系统层级的程序和一些对性能要求非常高的程序,如Mysql。
基于C语言的特性,有人就把库调用又向上抽象了一层,就是高级语言的解释器或虚拟机,如python的命令行界面、java的jvm。这一层已经与操作系统内核没有任何关系了。在这一层写的程序需要用内存时只需要申请分配即可,用完不需要手动进行释放,虚拟机会自动监视程序使用内存的情况,发现有程序用完了的内存就收到一个垃圾桶里,等垃圾桶满了再统一释放。这个过程就是垃圾回收机制,此垃圾回收机制在python和java中都是通用的。
3.4.3 垃圾回收机制的缺陷
有了垃圾回收机制以后,程序员写程序只需要申请分配内存,而无需手动释放内存,由虚拟机自动释放内存。如此一来就很难出现前面所说的一个程序覆盖其他程序的内存的情况了。
垃圾回收机制大大的解放了程序员的精力,但是其也有其缺陷。由于虚拟机很难猜测程序申请的内存什么时候不需要使用了,而且程序很可能申请了众多内存空间并且用完以后不再用了。为了完成垃圾回收,垃圾收集器就必须定期、周期性的扫描内存空间,看哪些内存已经没有被使用了,将其标记为垃圾,达到一定阀值以后(比如内存只有100M,当垃圾达到40M时)再统一回收。而垃圾回收是非常占资源的,因为在进行垃圾回收时,其他程序的运行过程就被打断了。这也就是Android手机用起来卡的原因,因为Android手机就是运行在一个java虚拟机中的。
3.5 自由软件
自由软件的特点:
a) 可以自由使用(学习和修改)
b) 可以自由分发
c) 可以自由创建衍生版
3.6 Linux的哲学思想
a) 一切皆文件(把几乎所有资源,包括硬件设备都组织为文件格式)
b) 由目的单一的小程序组成,一个程序只实现一个功能,组合小程序完成复杂任务
c) 尽量避免捕获用户接口(为实现脚本编程打下了基础,可以自动完成某些功能)
d) 配置文件保存为纯文本格式(用文本编辑器即可完成系统配置工作)
3.7 获取发行版的方式
a) http://mirrors.aliyun.com
b) http://mirrors.sohu.com
c) http://mirrors.163.com
3.8 终端
终端是用户与主机交互必然要用到的设备。
终端分为以下几类:
a) 物理终端:直接接入本机的显示器和键盘设备,也称作控制台console
b) 虚拟命令行终端:附加在物理终端之上的、以软件方式虚拟实现的终端。Centos 6默认启动6个虚拟终端
可以用Ctrl+Alt+Fn(F1-F6)进行虚拟命令行终端间的切换
c) 图形终端:附加在物理终端之上的、以软件方式虚拟实现的终端。但额外会提供桌面环境。
图形终端是虚拟终端的一种,可以在启动过图形终端的情况下使用Ctrl+Alt+F7在虚拟命令行终端与图形终端间切换
本文出自 “忘情居” 博客,请务必保留此出处http://itchentao.blog.51cto.com/5168625/1902723
原文地址:http://itchentao.blog.51cto.com/5168625/1902723