文章目录
进程之间的通信
- 进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息.
进程间通信的方法
管道(pipe)
- 与常称之为无名管道
- 是半双工的, 即数据只能在一个方向上流动, 具有固定的读端和写端
- 他只能用于具有亲缘关系的进程之间的通信, 无论是父子进行还是兄弟进程
- 他是存储于内存中的一个特殊文件, 对于这个文件的操作只能是read和write等函数
FIFO有名管道
- 可以在无关的进程之间进行通信, 这是与无名管道最大的区别
- 他是以一个特性的文件存储在文件系统中, 所以对他的操作与其路径名有关联
消息队列
- 消息队列是消息的连接表, 放在内核中, 一个消息队列由一个标识符表示
- 消息队列是面向记录的, 其中的消息具有特定的格式以及特定的优先级
- 消息队列独立于发送和接受进程中, 也就是当一个进程被销毁, 他在消息队列中的信息是不会被删除的
- 消息队列中的内容可以实现随机查询, 也就是消息不一定要以FIFO读取, 也可以按消息的类型读取
信号量
- 信号量与IPC结构不同, 他是一个计数器, 信号量用于实现进程之间的同步和互斥, 而不是用于进程间消息的通信的
- 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
- 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
- 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
共享内存
- 指两个或多个进程共享一个给定的存储区
- 共享内存是最快的一种 IPC,因为进程是直接对共享内存进行存取。
- 因为多个进程可以同时操作,所以需要进行同步。
- 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
同步和互斥:
他俩都是指散步在不同进程或线程之间不同的任务片段, 但是互斥要求就低, 只要保证一个公共资源同一时刻只能被一个进程或线程使用即可, 但是同步要求就高了, 他在多线程或者多进程状态下,不仅有互斥的要求, 还要求严格的按照某种规定好的顺序去执行, 这种顺序是依赖于某个特点的任务的, 比如B线程运行的数据必须是依赖于A线程的, 这就必须使用同步的概念
套接字
- 使用套接字也可以实现进程间的通信, 与其他机制不同的是, 它可以实现不同机器之前的进程间的通信
线程之间的通信
start() 与 intercept()
- 在一个线程中去开始和结束一个线程
同步–synchronized
- 使多个线程实现同步
信号量 --volatile
- 支持多个线程同时访问一个对象或者对象的成员变量,由于每个线程可以拥有这个变量的拷贝,所以程序在执行过程中,一个线程看到的变量并不一定是最新的。
关键字volatile可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。
等待/通知机制(wait/notify)
- 一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程
等待/通知机制使⽤的是使⽤同⼀个对象锁,如果你两个线程使
⽤的是不同的对象锁,那它们之间是不能⽤等待/通知机制通信的。
管道
- 管道是基于“管道流”的通信⽅式,管道输入/输出流要用于线程之间的数据传输,而传输的媒介为内存。
管道输入/输出流的体现:
基于字符的:PipedWriter 、 PipedReader 、
基于字节流的:PipedOutputStream 、 PipedInputStream
使⽤管道多半与I/O流相关。当我们⼀个线程需要先另⼀个线程发送⼀个信息(⽐如字符串)或者⽂件等等时,就需要使⽤管道通信了
像消息传递机制,通过管道,将一个线程中的消息发送给另一个
CountdownLatch
- 战争爆发了,D接到命令去保护ABC三个连队撤离。
有一个方案,ABC依次撤离,D最后(ABC依次撤离),作为D来讲,我只要保证三个部队过去就行,你们仨爱咋办咋办,那我掰指头算一下,走完仨就撤。
CyclicBarrier
- 这个就是好比一场比赛, 只有所有选手都跑完了, 这场比赛才算结束
- CyclicBarrier与CountDownLatch比较
- CountDownLatch:一个线程(或者多个),等待另外N个线程完成某个事情之后才能执行;
- CyclicBarrier:N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
- CountDownLatch:一次性的;CyclicBarrier:可以重复使用。
- CountDownLatch基于AQS;CyclicBarrier基于锁和Condition。本质上都是依赖于volatile和CAS实现的
用户态和内核态
定义
- 它代表的是操作系统需要体现出来的俩种CPU执行的程序的状态
- 内核态是运行操作系统的程序, 比如一些硬件设备
- 用户态是运行一些类似桌面程序和用户的程序
包含的指令不同
- 内核态的程序可以使用内核的特权指令, 比如IO,内存清零,修改时钟, 允许和静止一些终端
- 而用户态的程序只能使用内核的非特权指令, 比如算术运算, 访管指令, 读数指令
- 在内核中分为4个权限特技, R0表示的就是内核态, R3表示的就是用户态
- 不同级别能够运行的指令是不同的
状态切换
- 系统调用是用户态进程主动要求切换到内核态的一种方式, 用户态的进程通过系统调用来向操作系统申请他的帮助来实现某项任务, 而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
- 当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
- 当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作未完成完成收到外围设备的中断信号,系统处理完中断信号后会切换到 硬盘读写的中断处理程序中 执行后续操作等。
- 内核态到达用户态只需要设置程序的状态字PSW即可
中断
硬中断:
-
硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上(注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)。
-
处理中断的驱动是需要运行在CPU上的,因此,当中断产生的时候,CPU会中断当前正在运行的任务,来处理中断。在有多核心的系统上,一个中断通常只能中断一颗CPU(也有一种特殊的情况,就是在大型主机上是有硬件通道的,它可以在没有主CPU的支持下,可以同时处理多个中断。)。
-
硬中断可以直接中断CPU。它会引起内核中相关的代码被触发。对于那些需要花费一些时间去处理的进程,中断代码本身也可以被其他的硬中断中断。
-
对于时钟中断,内核调度代码会将当前正在运行的进程挂起,从而让其他的进程来运行。它的存在是为了让调度代码(或称为调度器)可以调度多任务。
软中断:
-
软中断的处理非常像硬中断。然而,它们仅仅是由当前正在运行的进程所产生的。
-
通常,软中断是一些对I/O的请求。这些请求会调用内核中可以调度I/O发生的程序。对于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。根据I/O模型的不同,进程或许会被挂起直到I/O完成,此时内核调度器就会选择另一个进程去运行。I/O可以在进程之间产生并且调度过程通常和磁盘I/O的方式是相同。
-
软中断仅与内核相联系。而内核主要负责对需要运行的任何其他的进程进行调度。一些内核允许设备驱动的一些部分存在于用户空间,并且当需要的时候内核也会调度这个进程去运行。
-
软中断并不会直接中断CPU。也只有当前正在运行的代码(或进程)才会产生软中断。这种中断是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求。有一个特殊的软中断是Yield调用,它的作用是请求内核调度器去查看是否有一些其他的进程可以运行。
区别
- 内核态与用户态是操作系统的两种运行级别,当程序运行在3级特权级上时,就可以称之为运行在用户态。因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;
- 当程序运行在0级特权级上时,就可以称之为运行在内核态。
- 运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态。
- 这两种状态的主要差别是:
处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理机是可被抢占的 ;
而处于核心态执行中的进程,则能访问所有的内存空间和对象,且所占有的处理机是不允许被抢占的。