程序编程基础(归纳)
本系列文章由jadeshu编写,转载请注明出处。https://blog.csdn.net/jadeshu/article/details/85137936
作者:jadeshu 邮箱: jadeshu@qq.com 欢迎邮件交流 有不正确的地方请指正,学习内容还需要深入
一.程序基础(重点)
1.1为什么需要操作系统?
因为在以前是直接操作硬件之上的,这样每个硬件不同都需要重新编写程序会很麻烦,这样人们就想到了将软件和硬件隔离,
让人、程序直接跟操作系统应用软件打交道,在让操作系统应用软件去控制硬件。操作系统也是一种应用软件,只是极其复杂!
1.2为什么需要内存管理器
因为需要代码安全和程序之间不干涉彼此的内存,同样使每个程序都有逻辑上的空间大小,具体如下图所示
1.3程序编写过程和加载过程(简述)
1.3.1程序编写过程:
我们平常写的代码为文本文件,进行编译后生成可执行文件!过程如下:
源码--->目标编译器----->生成对应目标平台的汇编源码(x86,ARM,MIPS)--->目标汇编器----->生成对应的二进制可执行程序
1)最早的是机器码(011000111)指令,不容易理解和记忆,发展出帮助人类记忆和使用的助记符,形成汇编指令,根据助记符与二进制的关系,从指令助记符转为二进制的机器码,这个工具就叫做汇编器,而这个助记符语言也就是我们的汇编语言,这个语言是人类从机器语言发展高级语言的第一步;
2)对应不同的处理器需要不同的汇编指令,就形成的x86汇编,ARM汇编等,也就要意味着同一样的逻辑代码就需要在x86,arm,mips上需要写不同的汇编代码,不具备可移植性,就此C语言诞生了
3)汇编语言是每一种CPU一种代码,而C语言使用同样的代码,只是编译器不一样, 编译器根据需要将C语言的代码编译出80x86或ARM或MIPS汇编,这样,代码编写完成后就具有可移植性, 在不同的平台上只要重新编译就可以了,无需要重新编写代码,而且现在主流的操作系统以及硬件平台都支持C语言编程(Java是编译成字节码,不同平台各有虚拟机即可实现跨平台);
*为了方便管理和应用,代码编译后将分为:
*a.代码段(可读)
*b.数据段(可读写) [我们编写代码时有些常量字符等会存入常量区不可写只可读]
*c.栈(代码运行时函数局部变量和保存执行上线文用的内存区域) (可读可写)
*d.堆(代码运行时分配的内存区域) (可读可写)
代码编译后确定的地址是虚拟地址/逻辑地址。
1.3.2程序加载过程:
当我们点击程序时,操作系统将程序(可执行文件)加载到内存中,CPU的CS:IP执行要运行的首地址代码处(即是代码段位置),CPU从该位置取一条指令执行一条指令;
*a 取一条指令后执行一条指令,CS:IP默认跳转到下一条指令位置。
*b 当取有些指令后,会改变CS:IP的地址,即发生跳转其他地址的位置。
请参看WIN32程序启动过程章节
1.4进程和线程
1.4.1进程
a.谈到进程则首先需要了解程序,程序是静态的,进程是运行时的程序;
b,当程序运行时,系统就将程序指令加载到内存中并分配系统资源;
c.进程是分配资源的单元
正在执行中的程序,其实就是应用程序在内存中运行的空间。
1.4.2线程
a.当程序运行系统分配资源产生进程,系统会产生一线程,叫主线程(CS:IP入口点执行的线程为主线程)
b.线程是CPU调度的基本单元,CPU执行单元是线程(在早期系统是以进程为运行单元的,系统开销较大)
线程是进程中的一个执行单元,一个进程中至少要有一个线程;一个进程中可以是有多个线程的,这样的程序也可以称为多线程程序;可以实现多路同时执行代码,专业术语称之为并发;多线程的使用可以合理使用
CPU的资源,如果线程过多会导致降低性能;CPU处理程序时,是通过快速切换完成的。
总结:
如1.3.2中介绍的当我们点击程序时,系统将程序(可执行文件的二进制指令)加载到指定的内存,这时候需要重定位内存位置(涉及到PE知识,想了解的请点击),我们编写的程序是虚拟地址,CPU内部有个MMU(内存管理单元)单元,专门处理内存映射到实际物理内存位置,我们不需要关心这个;同时系统内核会创建进程内核,分配系统资源(进程栈,堆等),同时创建一线程(主线程 拥有少量资源,创建和撤销开销小)给CPU调度