操作系统基础
什么是操作系统?
- 是管理计算机硬件和软件资源的程序。
- 是计算机系统的内核与基石。
- 为用户提供一个和系统交互的操作界面。
- 包含内核和外壳(shell)。
用户态(user mode)和系统态(kernel mode)
根据进程访问资源的特点,我们可以把进程在系统上的运行分为两种:用户态和系统态。
| 运行程序 | 内存访问范围 | 指令 | |
|---|---|---|---|
| 用户态 | 应用程序 | 受限制,只能访问用户储存空间 | 特权指令 |
| 系统态 | 系统程序 | 不受限制,可以访问计算机的任何资源,包括用户和系统的储存空间、系统中的硬件和软件 | 非特权指令 |
那么两种状态如何联系起来呢?
首先,大部分运行的程序都运行在用户态。只有小部分会进入系统态。在上述表格中提到的特权指令就会使程序进入系统态。用JavaGuide中的话来说,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。
这些系统调用按功能大致可分为如下几类:
- 设备管理。完成设备的请求或释放,以及设备启动等功能。
- 文件管理。完成文件的读、写、创建及删除等功能。
- 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。
- 进程通信。完成进程之间的消息传递或信号传递等功能。
- 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。
进程和线程
进程和线程区别
首先,线程是进程划分成的更小运行单位,一个进程在其执行过程中可以产生多个线程。
线程和进程最大的不同就是,进程之间是独立的,线程之间则不一定。
多个线程共享进程的堆(heap)。但是有自己的栈。
进程的状态
-
创建状态(new):正在被创建
-
就绪状态(ready):已处于准备运行状态。进程此时获得了除了处理器之外的一切所需资源,一旦得到处理器资源即可运行。
-
运行状态(running):进程正在处理器上运行。
-
阻塞状态(waiting):又称等待状态,进程正在等待某一事件而暂停运行,比如等待IO操作完成。即使处理器空闲,该进程也不能运行
-
结束状态(terminated)进程正在从系统中消失。可能是正常结束或因其他原因而中断退出
进程间的通信方式
这部分我引用了CSDN上帅地的文章,他实在是非常厉害。文章写的很好,循序渐进,有理有据。不是单纯的列举了对象的内容,特点。如果能基于他的思路去理解这些知识,相信你的理解也会更深入,对知识印象也会更深。原文链接:blog.csdn.net/m0_37907797…
1. 管道 (Pipe)
使用Linux中我们常用到|。 这就是管道。前一条的输出会作为后一条的输入。
这样说来,很明显,这种通信方式是单向的。
并且,这种管道是匿名的,对它,我们没有具体的名称。命名管道也是存在的,code例子如下, 这个例子创建了一个名为test的铜套:
mkfifo test
接下来再用一个使用该管道的例子来更仔细的说明管道。
// 向test管道中写数据
echo "this is a pipe" > test
// 从test管道中读出来
cat < test
需要注意的是:管道中数据没有被读出来的话,这个命令就会一直停在这里,只有当把数据读出来时,写数据的命令才会结束。
从这个例子中,可以看出,管道的通信机制类似于缓存。像是一个进程把数据放在摸个缓存区域,然后等待另一个进程来读取他。
他的优缺点有什么呢?
- 优点
- 非常简单,不需要我们再去创建对象。
- 能保证管道中的数据被其他进程拿走了
- 缺点
- 效率低下,只有在另一进程读取数据后,原进程才能返回
什么能让数据放至内存后,无需等待其他进程来读取立刻返回呢? 消息队列就可以回答这个问题。
2. 消息队列
A进程如果想要给B进程发送消息,只需要把消息放在对应的消息队列就行。B进程需要时再去对应的消息队列读取。这种方式也类似于缓存。
需要注意的是:消息队列是消息的链表,有特定的格式,存放在内存中。链表的实现我们知道是先进先出的,但是上一段中提到的对应是消息队列标识符标示的,也就是实现了消息的随机查询。
那么缺点有什么呢? 如果发送的数据内存比较大,并且两个进程之间通信非常频繁的话,消息队列就不大合适了。因为数据内醋比较大意味着发送消息这个过程需要很长时间来读内存。
3. 共享内存
消息队列的缺点可以很好的被共享内存这个通信方式来解决。拷贝消息所消耗的时间就不需要啦。
但是各进程之间是独立的,怎么共享内存呢?
首先,系统分配给进程的内存并非实际物理内存,而是虚拟内存空间。那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中。
这种方式需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
4. 信号量 Semaphore
信号量本质是一个计数器,用来实现进程之间的互斥与同步。
例如,初始值为1,然后A来访问时,我们把信号量设为0。这样B来访问时,发现是0就无法访问了。
5. 套接字 Socket
上面我们说的共享内存、管道、信号量、消息队列,他们都是多个进程在同一台主机之间的通信,那么不同主机上的进程用什么来通信呢?
答案是socket。socket是支持TCP/IP网络通信的基本操作单元。简单来说socket是通信两方的一种约定,用套接字中的相关函数来完成通信过程。
线程间同步的方式
首先,线程同步是在有两个或多个共享关键资源的线程的并发执行下,应该同步线程避免关键的资源使用冲突。操作系统一般有下面三种线程同步的方式:
-
互斥量(mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
-
信号量(semaphore):它允许同一时刻多个线程访问统一资源,但是需要控制同一时刻访问此资源的最大线程数量
-
事件:Wait/notify, 通过通知操作的方式来保持多线程同步,还可以实现多线程优先级的比较操作
进程的调度算法
调度是指进程的运行顺序。好的调度可以让CPU达到最大利用率。计算机科学家已经定义了一些算法:
-
先到先服务(FCFS)调度算法: 从就绪队列中选择一个最先进入该队列的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用CPU时再重新调度。
-
短作业优先(SJF)调度算法:从就绪队列中选择一个估计运行时间最短的进程为之分配资源,...如上...
-
时间片轮转(Round Robin)调度算法:每个进程被分配一个时间段,称作它的时间片。即该进程允许运行的时间。
-
多级反馈队列调度算法:目前被公认的一种较好的进程调度算法。对进程的优先级排序,给优先级高的进程分配更多的时间段。
-
优先级调度算法:为每个进程分配优先级,首先执行最高优先级的进程,以此类推。有tie时,以FCFS的方式执行。根据内存要求,时间要求,或者任何其他资源要求来确定优先级。
待续...