我是如何学习写一个操作系统(五):故事的高潮之进程和线程1

前言

为什么取这个标题呢?一是进程和线程是作为操作系统里最重要最核心的一部分。二是确实吃冰棍拉冰棍,没话,强行凑标题和之前的标题差不多字数。

前一章写了系统调用的过程,算是一个小插曲,这个部分不管在哪里应该都是可以的。

现在的这个系列已经和之前的标题渐行渐远了,原本是想以之前写的一个玩具型操作系统FragileOS为主线,但是在看书学习的过程中稍微改了一下方向,已经不是特别关注一个操作系统的实现的完整流程和内部的联系,更多的是想系统的学习操作系统的各个模块然后辅以一些代码,但是不管怎么样,都是属于自己在学习操作系统的过程的一个记录

进入正题

进程

进程的出现最最主要的原因就是想要提高CPU的利用率

进程的定义

  • 正在执行的程序
  • 正在计算机上执行的程序实例
  • 能够分配给处理器并由处理器执行的实体
  • 一组指令的执行、一个当前状态和相关的系统资源的集合

多进程的组织

单核CPU在同一时刻只能运行一条指令,所谓的多进程只是指令来回切换的假象,但是因为速度太快,就可以看成是同时进行的。所以在进程切换的时就需要去组织进程的切换

进程控制块(process control block)

控制进程的切换一个重要的数据结构就是进程控制块(process control block),是与每个进程相关的还有操作系统用于控制进程的许多属性的集合

进程控制块的作用,是使一个在多道程序环境下不能独立进行的程序(含数据),成为一个能独立运行的基本单位,一个能与其他进程并发执行的进程。或者说,操作系统是根据PCB来对并发执行的进程进行控制和管理。

一般情况下,PCB中包含以下内容:

  • 进程标识符(内部,外部)
  • 处理机的信息(通用寄存器,指令计数器,PSW,用户的栈指针)。
  • 进程调度信息(进程状态,进程的优先级,进程调度所需的其它信息,事件)
  • 进程控制信息(程序的数据的地址,资源清单,进程同步和通信机制,链接指针)

进程的五状态模型

进程的调度

一般来说,可能让进程发生切换有这几种事件:

但是随着PC的发展,这种从两方面情况发生了变化。第一,大多数时间都只有一个活跃的进程。毕竟一般来说,你在使用Word编辑文件时,不太可能还同时让系统在后台编译程序。这样的情况下,调度器其实不需要做很多工作来决定到底运行哪个进程——Word几乎就是唯一的选择。第二,计算机的速度越来越快,以至于CPU可能已经不再那么稀缺了。对于很多PC的程序来说,其限制主要在于用户能进行输入的比例,而不是CPU能够处理的比例。甚至就算是两个程序真的同时进行,其实先调度哪个运行也无伤大雅,例如,一个Word和一个Excel同时在运行,先调度哪个都行,因为用户可能同时在等待这两个程序的输出。

但是对于网络服务器来说,这种情况又不一样了。非常多的程序竞争CPU资源,因此,调度又变得非常重要了。举例来说,调度器需要决定到底是让日常统计进程运行还是让响应用户请求的进程运行。

调度器除了需要考虑选择哪个进程运行,还需要考虑到系统的性能。毕竟,进程之间的切换是开销很大的,这涉及到从用户态到内核状态的切换,进程状态的保存、恢复等等操作。

参考链接

进程的同步和合作

内存管理

在进程进行来回切换如何保证当前进程的运行不会影响其它进程的运行,比如对于一个内存进程的读写,就要保证不能越界

所以就需要一个机制来把进程之间的地址空间隔离开

进程的同步

不同进程间存在着不同的相互制约关系。为了协调进程之间的相互制约关系,达到资源共享和进程协作,避免进程之间的冲突,就需要进程同步的概念。

多个进程可以共享系统中的各种资源,但其中许多资源一次只能为一个进程所使用,我们把一次只允许一个进程使用的资源成为临界资源。
对临界资源的访问,必须互斥的进行。每个进程中,访问临界资源的那段代码成为临界区。
为了保证临界资源的正确使用,可以把临界资源的访问过程分为四个部分。

  • 进入区。为了进入临界区使用临界资源,在进入去要检查可否进入临界区。
  • 临界区。进程中访问临界资源的那段代码。
  • 退出区。将正在访问临界区的标志清除。
  • 剩余区。代码中的其余部分。

一般实现进程的同步有这几种方法:

  • 提过硬件提供的实现
  • 信号量
  • 管程

线程

进程是资源分配的最小单位,线程是CPU调度的最小单位

在进程的切换时还需要对内存资源的一个切换,但是线程则不需要对资源的切换,所以引入是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。

用户级线程和内核级线程

用户级线程是指不需要内核支持而在用户程序中实现的线程,内核对线程包一无所知。从内核角度考虑,就是按正常的方式管理,即单线程进程,但是它不能像内核级线程一样更好的运用多核CPU。

内核级线程建立和销毁都是由操作系统负责、通过系统调用完成的。在内核的支持下运行,无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。

  • 试想一下如果没有内核级线程,当用户级的一个线程进行到I/O阻塞时,将会导致所有的线程都堵塞,因为以操作系统的层面来看,它们都属于用一个进程,所以会直接切换进程,其它的线程就得不到执行
  • 在多处理器系统中,内核级线程能够真正的实现并行,能够执行同一进程内的多个线程

小结

这一篇主要是简略的总结书上的一些概念,没有干货,在后面进行代码实现的时候会再深入的去看。下一篇可能会去看Linux0.12在进程上面的实现。

原文地址:https://www.cnblogs.com/secoding/p/11417547.html

时间: 2024-09-28 13:37:52

我是如何学习写一个操作系统(五):故事的高潮之进程和线程1的相关文章

我是如何学习写一个操作系统(六):进程的调度

前言 既然引进了多进程,其实也就是在进程之间来回切换,那么就会有进程之间的调度问题.实则是在可运行进程之间分配有限的处理器时间资源的内核子系统. 几个简单的CPU调度算法 First Come, First Served(FCFS) 其实就是一个先进先出队列了,也就是说先申请的进程,先执行.当CPU空闲时,它会分配给位于队列头部的进程,并且这个运行进程从队列中移去.FCFS调度代码编写简单并且理解容易. 但是对于一个需要和用户进行交互的进程,这种调度算法就会造成体验非常不好,因为周转时间需要完成

我是如何学习写一个操作系统(三):操作系统的启动之保护模式

前言 上一篇其实已经说完了boot的大致工作,但是Linux在最后进入操作系统之前还有一些操作,比如进入保护模式.在我自己的FragileOS里进入保护模式是在引导程序结束后完成的. 实模式到保护模式属于操作系统的一个大坎,所以需要先提一下 从实模式到保护模式 实模式和保护模式都是CPU的工作模式,它们的主要区别就是寻址方式 实模式出现于早期8088CPU时期.当时由于CPU的性能有限,一共只有20位地址线(所以地址空间只有1MB),以及8个16位的通用寄存器,以及4个16位的段寄存器.所以为了

Android学习--写一个发送短信的apk,注意布局文件的处理过程!!!

刚开始写Android程序如图发现使用了findViewById方法之后输出的话居然是null(空指针错误),也就是说这个方法没有成功.网上说这样写是在activity_main .xml去找这个ID所代表的控件,而现在使用的ADT在layout下除了activity_main .xml还多生成了一个fragment_main.xml.我就是把控件写在了后一个布局文件中.想请问下,使用什么样的方法是在fragment_main.xml去寻找控件呢? 回答:在PlaceHolderFragment

Linux内核学习--写一个c程序,并在内核中编译,运行

20140506 今天开始学习伟大的开源代表作:Linux内核.之前的工作流于几个简单命令的应用,因着对Android操作系统的情愫,"忍不住"跟随陈利君老师的步伐,开启OS内核之旅.学习路径之一是直接从代码入手,下面来写一个hello.c内核模块. 说明: 这个路径/usr/src/linux-headers-2.6.32-22/include/linux是引用的头文件. 内核模块固定格式:module_init()/ module_exit(),module函数是从头文件中来的.

操作系统原理(二),进程、线程

Technorati 标签: 操作系统,原理 现代操作系统比如,Linux,Windows等,都是支持"多任务"的操作系统.所谓多任务,指的就是操作系统可以同时运行多个任务.也就是在同一台电脑上,可以同时上网.听歌.使用Word,在过去单核的CPU上都已经可以支持多任务,实现的方式是操作系统让各个任务轮流交替执行.,比如任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒,因为CPU执行速度非常块,我们感觉到所有任务都是并发处理. 到了多核CPU时代

初级篇第八期:学习写一个Model

学习建议:自己动手,丰衣足食 学习周期:1周 学习目的:熟练使用Obejct-C中基于NSObject的Model类 学习答疑:欢迎来技术群里提问并做分享 学习工具:Xcode开发环境 学习内容:熟悉Model的作用以及基本用法 我们在开发中为什么要创建Model,主要因为我们在接收服务器给我们返回的数据时候,我们需要用来保存这些数据,那么我们就会创建一个所谓的Model,其实就是基于NSObject类,然后创建一些它的属性,来保存相应的值,也方便其他的类来调用,当然了,我们要考虑在这个Mode

学习写一个能够将文件复制、解压到指定文件夹中的批处理文件

场景1:afoldersource中有若干文件夹和若干压缩文件,现在将afoldersource中的文件全部复制到afolderdist中. afoldersource: 脚本: @ECHO OFF ##关闭命令回显 echo copy file ##显示一句话 SET sourcepath=E:\afoldersource ##定义源地址 SET destpath=E:\afolderdist ##定义目标地址 rmdir %destpath%\folder /s /q ##删除目标地址中的文

近期小感——一个残疾人写的操作系统

因为自己也在写一个操作系统的内核,虽然没完成,也遇到很多困难,参考了诸如Linux 0.01 ,minix3.0, Orange's等,总算有点起色吧,属于走一步看一步那种,从实模式怎么跳到保护模式,从怎么打开关闭中断,再到怎么读取内存大小,都是一步一步来,很多内容都是从网上搜索,看资料等,而且我的引导扇区也是用的nasm汇编,实在反感ATT格式汇编,毕竟大学学得汇编是在windows下的的intel格式. 扯了这么多犊子,还是想说,我在搜索决定写宏内核还是微内核时,碰到了一个人从10年就开始搞

Webpack-源码三,从源码分析如何写一个plugin

经过上一篇博客分析webpack从命令行到打包完成的整体流程,我们知道了webpage的plugin是基于事件机制工作的,这样最大的好处是易于扩展.社区里很多webpack的plugin,但是具体到我们的项目并不一定适用,这篇博客告诉你如何入手写一个plugin,然后分析源码相关部分告诉你你的plugin是如何工作.知其然且知其所以然. 该系列博客的所有测试代码. 从黑盒角度学习写一个plugin 所谓黑盒,就是先不管webpack的plugin如何运作,只去看官网介绍. Compiler和Co