操作系统学习心得

单核CPU一个时刻只能做一件事,基准速度指的是单核的基准速度,句柄是变量

四核CPU一个核一个时刻只能执行一个线程,所以CPU执行任务的时候是在快速切换任务,对应着分时操作系统

  • 一个物理CPU可以有1个或者多个物理内核,
  • 一个物理内核可以作为1个或者2个逻辑CPU
  • 有多少个逻辑处理器,就可以开多少个线程。
  • 操作系统可以使用逻辑CPU来模拟真实CPU。

在没有多核处理器的时候,一个物理CPU只能有一个物理内核,

有了多核技术,一个物理CPU可以有多个物理内核,可以把一个CPU当作多个CPU使用,即逻辑CPU。

没有开启超线程时,逻辑CPU的个数就是总的CPU物理内核数。

开启超线程后,逻辑CPU的个数就是总的CPU物理内核数的两倍。

linux一个任务20ms左右,Windows几十毫秒不确定

核的虚拟化

虚拟化,2核4G的服务器虚拟出来的 8核16G的服务器,但是每个核只有一个逻辑电路,每个时刻同一时间单位一个核只能跑一个任务,虽然模拟出了多个核,但是同一时刻还是只能跑之前的核数

腾讯云1核2G的学生版服务区器可能是 2核4G的服务器虚拟出来的 8核16G的服务器,然后卖给8个人,这样的前提是这8个人不同时使用这个服务器

CPU读取内存的数据首先要指定地址,比如读取10000字节需要下达10000次地址指令,所以操作系统在内存中会把数据尽可能的连续存储,为了提高速度,操作系统下达一次地址指令会把之后的4KB一次性读取过来,这样更方便cpu调用;一次性读取的数据大小就是操作系统页的大小;现在的操作系统的页大小基本都是4KB;

页的目的是加快读取;如果一个页存放多个变量,那么它们的新逻辑地址是相同的,出现地址冲突,这样就限制了一个页存放一个变量,所以操作系统分配变量就是按照页分配的,牺牲空间来提升时间,这是对于基本类型数据,相比较于类和数组,一个变量占用空间比一个页要大;

理论上用Java查看变量使用的是基本类型的空间大小,但是在操作系统上实际是使用一个页的大小;
原地址不可变的原因:引用类型空间大小不确定,因为数据排队储存,所以换数据时不能变化空间大小,需要重新使用一个空间(这里的一个空间表示一个页),小的数据不够占用一个页,空间充足也不允许变化内容,因为大部分数据都是超过一个页大小,其实是Java自身的检测机制不允许在原地扩容,任何语言都不允许;

CPU高速缓存

在Java中Boolean类型底层用 int 类型表示,所以分配给它的是32个字节—>在CPU高速缓存区里存储单位是缓存行,每一个缓存行存储64字节,因为通过总线读取时需要通过电压传递,缓存行里面的数据的读取是需要排队的,数据越小排队的越多,所以让boolean类型数据变大,运行就会越快;

协程,纤程

2.什么是协程?

协程全称为协同程序,又称作微线程。它与多线程情况下的线程比较类似。协程有自己的堆栈、局部变量和指令指针,通过,多个协程共享全局变量等很多信息。其思想是,一系列相互依赖的协程依次使用CPU,每次只有一个协程运行,其他协程处于休眠状态。协程实际上是在一个线程当中,每个协程对CPU进行分时访问。

线程和协程的主要区别在于:在多处理器的情况下,多线程程序可以同时运行多个线程;而协同程序需要通过协作来完成,在任一时刻只有一个协同程序在运行。

3.什么是纤程?

纤程是比线程更小的一个运行单位。一个线程可以拆分为多个纤程,然后通过人工转换,从而让各个纤程工作。

纤程起始就是线程里面创建的多个执行任务。

LRU

最近最少使用算法在缓存写满的时候,会根据所有数据的访问记录,淘汰掉未来被访问几率最低的数据。也就是说该算法认为,最近被访问过的数据,在将来被访问的几率最大

  1. 假设我们有一块内存,一共能够存储 5 数据块。
  2. 依次向内存存入A、B、C、D、E,此时内存已经存满。
  3. 再次插入新的数据时,会将在内存存放时间最久的数据A淘汰掉。
  4. 当我们在外部再次读取数据B时,已经处于末尾的B会被标记为活跃状态,提到头部,数据C就变成了存放时间最久的数据。
  5. 再次插入新的数据G,存放时间最久的数据C就会被淘汰掉。
import java.util.HashMap;
import java.util.Map;

public class LRUCache {
    
     public static class Entry{
        public Entry pre; //双向链表的前驱结点
        public Entry next; //双向链表的后驱结点
        public int key;     //查询缓存的key
        public int value;   //查询缓存的value  存储的是双向链表的Entry结点

        public Entry() {
        }
        public Entry(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }


    Entry head,tail;//Entry类型的头结点和尾结点
    int capacity;  //缓存的容量
    int size;       //当前缓存存入数据的个数
    Map<Integer,Entry> cache; //定义hashMap为了快速去查找

    public LRUCache(int capacity) {
        this.capacity = capacity;
        initLinkedList(); //初始化链表
        size=0;
        cache=new HashMap<>(capacity+2); //初始化hashMap
    }

   
    /**
     * 初始化链表
     */
    private void initLinkedList(){
        head = new Entry();
        tail = new Entry();

        head.next = tail;
        tail.pre = head;
    }

    /**
     * 将结点加入到头结点,如果容量已满,删除尾结点
     */
    public void put(int key,int value){ //类型最好是泛型
        Entry node = cache.get(key); //通过缓存的key值查找有没有这个结点
        if (node != null){ //说明缓存有这个值
            node.value = value; //把新的值覆盖掉旧值
            moveToHead(node);//然后把结点移动到头结点
            return;
        }

        //不存在,先加进去,再移除尾结点
        //此时容量已满,删除尾结点
        if (size ==  capacity){
            Entry lastNode = tail.pre; //最后一个结点
            deleteNode(lastNode);   //删除最后一个结点
            cache.remove(lastNode.key); //然后在缓存中也需要给它删掉
            size--;
        }

        //加入头结点
        Entry newNode = new Entry();
        newNode.key = key;          //把新加入的key和value赋值
        newNode.value = value;
        addNode(newNode);       //加入到头结点
        cache.put(key,newNode); //缓存也加入key和value
        size++;
    }


    /**
     *  取缓存
     */
    public int get(int key){
        Entry node  = cache.get(key);
        if (node == null){
            return -1;
        }
        //移动存在结点
        moveToHead(node);
        return node.value;
    }


    /**
     *要想把插入的结点移动到头结点,必须先删除结点,然后再插入结点
     * @param node
     */
    private void moveToHead(Entry node) {
        deleteNode(node);
        addNode(node);
    }

    private void addNode(Entry node) {
        head.next.pre= node;
        node.next = head.next;

        node.pre = head;
        head.next = node;
    }

    private void deleteNode(Entry node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    public static void main(String[] args) {
        LRUCache cache = new LRUCache(2);

        cache.put(1,1);
        cache.put(2,2);//21
        System.out.println(cache.get(1));//12
        cache.put(3,3);//31
        System.out.println(cache.get(2));
    }
}

银行家算法

将操作系统视为银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款

操作系统按照银行家制定的规则为进程分配资源。进程运行之前先声明对各种资源的最大需求量,当进程在执行继续申请资源是,先测试该进程已占用的资源数与本次申请的资源数之和是否超过该进程声明的最大需求量

若超过则拒绝分配资源,若未超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前申请量分配资源,否则也要推迟分配。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEa3vDIH-1670228506333)(…/img/image-20220913143720885.png)]

操作系统的的由来是什么?

电脑是由硬件组成,硬件依靠总线(导线)相连,机器语言压缩映射成汇编语言,汇编语言压缩成C语言。硬件生产商在生产硬件时也开发了操作硬件的驱动,通过使用生产商编写的方法,来使用硬件,显示器有显卡驱动,喇叭有声卡驱动等,实现一个电脑操作往往需要调动多种驱动协同工作。这样使用起来仍有难度,所以有人编写了方法来指挥驱动协同工作,这就是操作系统内核。现代操作系统的所有方法都是由操作系统内核提供的,现代操作系统的方法支撑了许多程序,不管用哪种语言的程序最终都会翻译成汇编语言和C。

硬件——驱动——操作系统内核——现代操作系统

操作系统内核

一个硬件对应一个程序 (驱动)驱动:驱动某个硬件执行

操作系统内核的产生:

封装了一系列方法 写了如·何组合工作驱动 内核控制最基本的功能

所以操作系统的内核就是操作驱动 ,驱动又和硬件相连

无论哪种语言最后都转化成汇编语言或者C语言 然后操作驱动 推动硬件执行

操作系统是由操作系统内核衍生出的 内核功能的扩展 形成一个完整的操作系统

所以如果程序是基于内核研发的 就可以在window任何一个版本上使用 如果基于操作系统开发的 如果换了版本就不能使用了

操作系统安装程序的内部原理是什么

开发工具和操作系统有约定,开发工具把方法打包成.exe文件 .exe实际是一个压缩包, .exe中的文件包含(主方法路径 程序图标以及程序图标所在路径 可识别编码,可识别文件扩展名 )和 程序代码

程序代码会被操作系统翻译成操作系统能识别的汇编语言和C语言,所以安装的时候,因为操作系统约定了注册表的位置,可识别文件类型注册表,图片的路径,开机启动的注册表信息,开机时通过注册表的信息查找程序所在的磁盘,将磁盘的数据加载到内存中,再根据主程序的地址开始执行。一点击桌面上的图标 操作系统会找到.exe文件的主方法 然后执行程序代码

显示屏原理

显示器由像素点组成

每一个像素点由坐标(两个数字)、亮度、颜色(由三原色组成 红绿蓝,由三个数组成(最高255),数值越高亮度越亮)组成。总共56bit

**显示器怎么把数据显示到显示屏上呢?**内存把数据以0101比特流的方式传输过来 然后显示屏解析每56bit位一个像素点 像素点包含着坐标、亮度和颜色,然后解析到显示屏上

显示屏上显示的文字什么的 ,实际上是每个文字都对应bit的排列组合,实际上就是编码,编码 ASCII编码 8位 能表示256种编码,Unicode 16位 能标记6万多种比特信息

一套编码对应一套形状库,形状库存在磁盘当中 当运行的时候会运行到内存中

断点续传、视频加载

断点续传和视频加载技术都是 文件的切割 将一个文件按照一定的规则人为的分割成多个小文件,然后客户端每次只上传一个小文件(当然我们也可以利用多线程技术每次上传多个小文件),服务器接收到上传过来的小文件后根据一定的规则来组合这些小文件。如果在上传过程中出现网络中断等意外情况,下次再次上传时可以从已经上传的部分继续上传,而不是重新上传。

断点续传 一个文件 分成等大 子文件 传递过程断网了 重新传能续上(子文件也需要编序号,也需要拆分)

视频加载技术 一个视频分成若干子视频 边加载边播放

记事本原理

记事本中存储的不是屏幕上展现出来的点阵信息,如果全部存储点阵信息,那么占用大量的存储空间,记事本本质上使用的是编码,计算机通过我们输入的一串串的编码,实际上是比特流,前八位记录是哪种编码因为是数据连续的,在记事本中显示数据不需要考虑位置 ,然后每次都取等长的位数 所以一般都借助byte[]数组,用数组记录编码,

输入法通过自身程序将键入的信息转成相关编码后,便会将这些编码实时上传到内存,记事本程序会监测编码信息,会将这些编码信息传入到计算机本地的编码库上,根据用户指定的方式进行解码。

计算机的编码库中,通常会存储编码的相应解码方式,一套编码对应一套形状库,展示在屏幕上。

pdf的内部实现原理是什么

pdf的内部实现原理是,相关的文本编辑程序或者文件转换程序读取某个文本文件,将这个文本文件的信息流按照相关的编码规则进行分段,然后在编码库中搜索,以及样式的相关运算,最终这个程序可以得到一个有这个文本文件映射而来的点阵信息文件,这个点阵信息文件并不会被立即显示到显示屏上去,而是会进行一些简化运算,并最终得到一份和原来的文本文件看上去一样的像素点阵文件,之后该程序会将该文件保存为pdf格式的文件。而pdf格式的文件其本身就是按照相关编码比对以及数学矢量运算得到的点阵图文件,其内部每个字符的保存方式不再是编码,而是真正的点阵信息,文本编辑文件在显示pdf文件的时候不会再进行编码和编码库中的编码比对的过程,而是直接将pdf的文件流发送到显存中去,因此pdf文件的显示,打印等速度会非常快,因为直接就是点阵信息而少了字符转码的过程,但与之对应的是,pdf文件的空间占用会比较大,且pdf不能很好的被修改,因为其内部不是修改方便的编码,而是真正的点阵信息,在修改pdf文件时需要删除一个点阵信息再加入一个点阵信息,这就会涉及到更大量的数据操作与运算,因此改起来比较麻烦,pdf文件分为两种,一种是完全被映射为纯点阵信息的pdf文件,这种pdf文件完全是以图片的形式存储的,打印容易但是完全不能被修改,另外一种pdf文件中则是以点阵信息存储的,这种pdf文件可以被修改,但是修改起来比较耗时。

word文档的内部实现原理是什么

记事本在存储文件时存储的是编码,在进行文本展示时会将这些编码根据编码库中的编码进行匹配解析,解析得到的点阵信息直接发送给显存,进而显现出来。

Word的实现原理和记事本非常类似,只不过加了非常多的辅助技能以及加装了字体库,这样一来文本信息不止步于基础的编码,每一种基础的语言编码不再有单调的形状,而是具有了很多的扩展形状,Word可以对键入的编码进行修饰,进而改造成字体库中字体编码可以识别的编码,进而使用字体库中的其他字体的编码进行解码,这样一来就可以解码出更加有趣的形状

同时,同样的字体,如楷体,可以等比例放大缩小,变颜色。理论上讲,Word中的每一种字体和颜色,以及大小,样式也都具备自己的编码,因为他们的形状不同。然而这样做的话就会需要大量的额外空间进行编码存储,因此在Word和中并不会单纯的通过不同样式的字体文件扩充字体库来进行同一字体不同样式的展现,而是采用了矢量计算的方式解决这个问题,也就是说直接对点阵信息进行函数计算,让它表现出各种样式,而不是真的为其设计一款自己的点阵信息,也就是说某个字可能只有一个点阵形状,它对应的其他形状的编码并没有自己的点阵信息来对应,有的只是一个矢量计算函数,这个函数可以让这个点阵信息在不失真的情况下发生各种颜色变化以及形变,进而进一步节省了空间。

这种矢量计算是非常耗费时间的,但是它节省空间,因此Word采取了一种折中的办法,即对于常用字体,它的每一种大小,颜色变化等样式形状,确确实实真的有一个字体文件与之对应,然而对于一些不常用的字体,就需要一个函数进行矢量计算了。Word的占用空间多,就是因为Word自带了更多的字体文件,因此很多人都说“Word快”,实际上Word是牺牲了空间获取了时间,当遇到生僻字体时,Word同样需要进行长时间的运算才能更改字体的样式。

驱动的作用,驱动和操作系统内核的关系

1.驱动的一般功能是:对设备初始化和释放、把数据从内核传送到硬件和从硬件读取数据、读取应用程序传送给设备文件的数据和回送应用程序请求的数据、检测和处理设备出现的错误等。

即对于常用字体,它的每一种大小,颜色变化等样式形状,确确实实真的有一个字体文件与之对应,然而对于一些不常用的字体,就需要一个函数进行矢量计算了。Word的占用空间多,就是因为Word自带了更多的字体文件,因此很多人都说“Word快”,实际上Word是牺牲了空间获取了时间,当遇到生僻字体时,Word同样需要进行长时间的运算才能更改字体的样式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值