应用层一般专一于API的使用,认为将其当作是一个黑盒便可,但了解操做系统的一些机制将有助于咱们更好地使用它,也有助于避免犯错误。linux
1969年,unix从贝尔实验室诞生,由一个失败的操做系统multics发展而来,它发布时带上了源码,以致于不少组织都对其进一步改进。它由C语言编写,且只有几百个系统调用,秉承一切皆文件的设计思想。算法
由芬兰大学生linus在1991年开发,基于Intel80386微处理器,开发完后就在因特网发布了源码。它借鉴了unix的不少设计思想,但它的实现彻底不一样,算是一个不一样的操做系统。开源协议很是自由,能够自由修改,但须要将改过的源码继续发布出来。shell
操做系统负责最基本的功能和系统管理,包括内核、设备驱动、启动引导、shell、界面、文件管理、其它系统工具。应用程序一般经过库函数,库函数经过系统调用让内核去完成各类任务。数据结构
进程是处于执行期的程序,它包含各类资源,好比文件、信号、内核数据、处理器状态、内存空间、执行线程、全局数据段等。进程提供了虚拟处理器和虚拟内存,看起来进程就像本身独享相应资源。并发
内核将全部进程保存在任务队列中,它是一个双向循环链表,该链表中每一个节点的类型都是task_struct进程描述符结构,处于<linux/sched.h>中。机器学习
全部进程都是PID为1的init进程的后代,内核启动的最后阶段启动init进程,它负责读取系统的初始化脚本并执行其它相关程序。每一个进程都有一个父进程,每一个进程也均可以有零个或多个子进程。fork()用于建立子进程,它经过拷贝当前进程来建立一个子进程,父子进程区别在于PID、PPID、某些资源、统计量不一样。fork()使用了写时拷贝机制,父进程和子进程共享同一个拷贝,只有须要写入时数据才会被复制。fork()的实际开销就是复制父进程的页表以及给子进程建立惟一进程描述符。exec()负责读取可执行文件并将其载入空间开始运行。进程调用exit()系统调用时进程被终结。分布式
线程是进程的活动对象,每一个线程都拥有独立的程序计数器、进程栈和一组寄存器。线程能在同一程序里面共享内存地址空间,共享文件和其它资源。从内核角度来讲linux并无线程这个概念,它将线程当成是进程来看待。内核线程没有独立的地址空间,只运行在内核空间,从不切换到用户空间。模块化
进程调度器的目的就是最大限度地利用CPU时间,只要有可执行的任务就要尽可能去执行它们,但咱们知道系统中几乎老是任务数大于处理器个数,因此确定某个时刻有任务得不到执行。多任务系统能并发地执行多个进程,一个CPU时是一对多,多个CPU时是多对多,全部任务看起来就像是同时在运行同样。函数
多任务系统分为抢占式和非抢占式,linux是抢占式调度,调度程序来决定进程的挂起和执行,每一个进程能执行的时间为时间片,现代系统通常都有必定的策略来动态分配时间片。非抢占式则是由进程本身主动中止,不然将一直运行下去,调度程序没法决定进程的运行中止,若是某个进程一直运行则会使系统奔溃。工具
进程可分为I/O密集型和处理器密集型。前者大部分时间进行各类I/O请求,一般这些进程只运行很短一段时间,而后就在I/O上阻塞了。然后者则是大部分时间都用于代码执行上,不停地运行并且没有什么I/O请求。固然有些进程既是I/O密集型也是处理器密集型。对于前者咱们但愿时间片少一点,对于后者咱们但愿时间片多一点,调度策略就是要在两个矛盾中找到平衡,使得进程可以响应迅速又能最大系统利用率。
基于优先级的调度是最基本的一种调度算法,它把进程进行了分级,优先级高的先运行,优先级低的后运行,相同优先级的进程则轮流运行。某些系统中优先级高的进程将更频繁运行,且时间片也更长。调度程序选择时间片未用尽且优先级最高的进程来执行。linux有两种优先级范围,第一种是nice值,从-20到+19,默认为0,值越大优先级越低。第二种是实时优先级,默认范围是0到99,值越高表示优先级越高。任何实时进程的优先级都高于普通进程,也就是说nice优先级和实时优先级是两个不一样维度。
时间片是进程在被抢占前所能持续运行的时间,默认的时间片大小不容易肯定,时间片太长会使交互响应变差,时间片过短会增长进程切换带来的损耗。也就是前面说到的矛盾,I/O密集型但愿时间片短点,而处理器密集型则但愿时间片长点。
linux采用了彻底公平调度(CFS)算法,它是一个针对普通进程的调度器,linux中称为SCHED_NORMAL,而POSIX则称为SCHED_OTHRER,实现类在kernel/sched_fair.c中。CFS容许每一个进程运行一段时间、循环轮转、选择运行最少的进程做为待运行进程,CFS计算全部可运行进程总数做为基础,再计算一个进程应该运行多久,而不是靠优先级来计算时间片。CFS有一个最小时间片(最小粒度),默认是1ms。也就是说就算有无穷大个进程,每一个进程最少也能有1ms时间片。CFS确保给每一个进程公平的处理器使用比。
linux提供了两种实时调度策略:SCHED_FIFO和SCHED_RR。前者是一种简单的先入先出调度算法,它不使用时间片。处于SCHED_FIFO级别的进程会比任何SCHED_NORMAL级别的进程先获得调度。一旦某个SCHED_FIFO级别的进程处于可执行状态,它将会一直执行,直到它本身阻塞或显示释放CPU。只有更高优先级的SCHED_FIFO或SCHED_RR进程才能抢占它。两个相同优先级的SCHED_FIFO级别的进程会轮流执行,其它普通进程只能等它变为不可运行状态后才有机会执行。
SCHED_RR大体与SCHED_FIFO相同,但它是耗尽事先分配的时间后就再也不继续执行,即SCHED_RR是带了时间片的SCHED_FIFO。时间片只是相对于同一优先级的进程,低优先级的进程没法抢占SCHED_RR任务,即便它的时间片耗尽也不行。
linux 经过sched_yield()系统调用来放弃当前进程的处理器时间,让给其余待执行进行,对于实时进程,它会将进程从活动队列中移到其优先级队列的后面。早期linux的yield语义不同,只会将进程放到优先级队列的末尾,放弃的时间不会太长。
专一于人工智能、读书与感想、聊聊数学、计算机科学、分布式、机器学习、深度学习、天然语言处理、算法与数据结构、Java深度、Tomcat内核等。