一.操作系统:是一款做软件与硬件管理的软件
操作系统与硬件之间有一个层次叫做驱动
硬件<-驱动<-操作系统(核心层)<-外壳<-用户(最外层到最底层)
对操作系统而言,对下要管理各种软件与硬件,对上而言,要提供各种使用方式对于用户
内核:对下
外壳:对上
二.系统调用:调用的是一个个的函数,是操作系统提供的接口(操作系统给的一个个函数接口,用来进行各种操作)
库函数是基于系统调用的二次开发,节省开发成本,增减代码移植性
操作系统内核的四大要点
进程管理,内存管理,设备管理,文件管理
这里我们不做过多叙述,这里只是一个概念描述
三.进程概念:
程序的一个执行实例
正在执行的程序
能分配处理器并由处理器执行的实体
这三种说法都是对的
那么正式进入进程的认识吧
内核:担当分配和管理系统资源(CPU时间,内存)的实体
管理的两个步骤:描述,组织
操作系统对进程进行管理,都是对结构体数据(PCB(进程描述符,是一个结构体,包含了进程的所有描述信息))进行管理
进程与可执行程序的区别:
1>进程是动态的,进程状态是可以改变的;程序是静态的,处于存储状态
2>进程在内存上,程序在硬盘上
3>进程比程序多了很多的描述信息,其中最重要的是PCB(进程控制块),PCB经常改变
进程控制块:是task_struck结构体,这个结构体具体的实现我会之后写到,其中进程控制块包含了标识符,状态,优先级,程序计数器,内存指针,上下文数据,I/O状态信息,记账信息 等!
*1>标识符:描述本进程的唯一标识符,用来区别其他进程
*2>状态:任务状态,退出代码,退出信号等
*3>优先级:相对于其他进程的优先级
*4>程序计数器:程序中即将被执行的下一条指令的地址。
5>内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
*6>上下文数据:进程执行时处理器的寄存器中的数据
7>I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表
8>记账信息:包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
所有运行在系统里的进程都以task_struck链表的形式存在内核里
四.进程位置
./目标文件 :执行可执行程序,并将程序加载到内存当中变成进程
这里介绍一些指令
ps aux指令:显示所有进程
grep行过滤
pid进程id
ps aux | grep “目标进程”:显示所要查询的进程信息
getpid() 获得系统调用的进程id,返回值为pid_t类型,是一个被封装过的类型,为一个无符号整数
getppid() 获得系统调用的父进程id,同样返回一个无符号整数
Linux下创建 子进程 的方法
fork指令:有两个返回值,创建子进程,成功给子进程返回0,给父进程返回子进程的pid;失败的时候给父进内容程返回-1;
子进程
1>子进程的数据结构以父进程为模板,共享代码
2>子进程数据私有,方法是写时拷贝
fork创建的子进程通常是要用来干其他事情的,经常用if eles来执行相应命令
Linux下c语言中的地址空间是虚拟地址,创建的变量i,用fork创建子进程,&i直接打印出来的地址其实是虚拟地址,但是i的输出是从物理地址中取得的
,所以才会出现同一个虚拟地址中的打印的值不同,因为他们的物理地址不同。
如下
我们可以清楚地看到fork成功的创建了一个子进程,父进程和子进程之间的关系也很清楚,子进程中调用getppid()函数的到的id正是父进程中getpid()得到的id,这也就说明了子进程已经被创建
并且我们可以看见同一个变量i在子进程和父进程中的地址是相同的,但是值却不同,这在我们通常的认知中这简直是不可能的,这里我们就引入了一个概念叫做虚拟地址,也就是代码中变量所指向的地址其实是一个虚拟地址,但是每一个虚拟地址通过页表映射转换为物理内存,也就是真正的的存储空间,来让我们看看这是一个怎样的过程
Linux下的任何语言的地址空间都是虚拟地址!!!!!
页表:4k大小是一页,在里面,操作系统中的mmu(硬件)将虚拟内存 映射 为物理内存
父进程与子进程共享代码:经过页表同时只想一块物理地址
父进程与子进程私有数据:经过页表指向不同的物理地址