当前位置 博文首页 > nameofcsdn的博客:操作系统

    nameofcsdn的博客:操作系统

    作者:[db:作者] 时间:2021-07-12 10:02

    目录

    1,计算机基本结构

    2,设备驱动

    3,进程和线程

    4,线程调度

    5,Linux系统的进程和线程

    6,原子操作、同步、锁

    7,可重入

    8,过度优化 VS?线程安全


    1,计算机基本结构

    计算机可以分成CPU、内存、IO设备、其他部件。

    总线(BUS)是用来连接所有部件的。

    后来人们设计了高速设备处理的北桥芯片、低速设备处理的南桥芯片。

    北桥PCI连接CPU、内存等,南桥ISA连接低速设备,

    系统总线是PCI BUS,低速设备采用ISA总线汇总到南桥,高速设备有各自的总线汇总到北桥。

    2,设备驱动

    对于硬件设备,操作系统中的硬件驱动程序来实现具体操作,向上提供统一的访问模式,软件开发只需要调用接口。

    设备驱动由设备厂商开发,操作系统开发者为设备厂商提供接口,按照该接口开发的驱动就可以在该操作系统上使用。

    3,进程和线程

    每个进程都有自己的独立内存空间。

    线程,也可以成为轻量级进程,一个进程由一个到多个线程组成。

    4,线程调度

    CPU的运行被切割成时间片,每个时间片运行一个线程,不断切换运行线程。

    线程至少有3个状态:运行running、就绪ready、等待waiting

    5,Linux系统的进程和线程

    6,原子操作、同步、锁

    一个独立的不被其他操作影响的操作叫原子操作。

    线程是共享数据的,为了避免同时读写导致数据异常,需要对数据进行访问同步,即一个线程访问的时候另外一个线程不能访问,这样的访问就是原子操作。

    同步的最常见方法就是锁。

    常见的锁:信号量、互斥量、临界区、读写锁、条件变量

    7,可重入

    函数重入

    函数可重入指的是,该函数重入之后,不会产生任何不良后果。

    可重入函数的特点:

    8,过度优化 VS?线程安全

    (1)一些复杂的优化行为,会让锁失效。

    案例一:将变量写入寄存器而不写回

    编译器为了提高访问速度,将变量x写入寄存器而不写回,可能导致最终x的值是1,本来应该是2的。

    案例二:交换指令顺序

    编译器可能会为了提高效率而交换相邻两条无关指令的顺序,CPU的动态调度功能也会交换指令执行的顺序

    这样,最终结果可能就是r1=r2=0,本来是不可能这样的。

    (2)使用volatile关键字,可以阻止编译器为了提高访问速度,将变量x写入寄存器而不写回,可以阻止编译器操作volatile变量的指令顺序。

    所以,volatile可以解决案例一,但是无法解决案例二,因为CPU有动态调度。

    (3)单例模式的double-check

    案例三:还是交换指令顺序

    这个是单例模式,申请一个对象,双重if判断是为了降低lock的调用,提高效率。

    而(2)(3)的顺序是可以颠倒的,所以如果函数并发调用,就会有一个正在调用构造函数的对象的指针,被提供给调用方,从而引发错误。

    CPU通常会提供一条屏障指令,用来组织指令交换顺序的时候穿过屏障,有的叫barrier,有的叫lwsync

    例如,可以这样来解决上面的问题:

    ?

    ?

    cs