信号量

操作系统中的互斥和JVM中的互斥

末鹿安然 提交于 2019-11-28 20:22:58
前几天再写synchronized的JVM实现时候,想起如果是2个线程同时想获得对象锁,即修改对象头的lock位时候,同时发现对象锁可用,同时修改lock的值,天了噜想想真是太可怕,想解决互斥却在解决方法中也有互斥的问题。后来发现: 任何互斥尝试必须基于一些基础硬件的互斥! 任何互斥尝试必须基于一些基础硬件的互斥! 任何互斥尝试必须基于一些基础硬件的互斥! 重要的话要说3遍!! 那我们来看看硬件的支持吧。 1、中断禁用 在单处理器中,并发进程不能同时执行,只能交替。因此要保证互斥,只需要保证一个进程不被中断就行,这种能力可以通过系统内核启用中断和禁止中断定义的原语实现。 禁用中断 临界区 启用中断 这种方法代价很高,因为处理器只能交替执行程序。还有个问题对于多处理器并没有什么用。 2、专用机器指令 在多处理器中,所有处理器都是共享内存。所以要保证互斥,在硬件级别上,对存储单位的访问要排斥对相同单位的其他访问。基于这一点,处理器设计者设计了一些机器指令,来保证两个动作的完整性,如我们喜闻乐见的compareAndSwap。 机器指令方法使用了忙等待。可能饥饿,导致某些进程无限期进入临界区。最重要的是可能产生死锁,假设进程P1通过CAS进入临界区,但是在临界区的时候被迫中断把处理器让给优先级别更高的P2,如果P2想使用同一资源,由于互斥机制,那么P2将永远无法进入临界区。

线程基础

﹥>﹥吖頭↗ 提交于 2019-11-28 17:33:45
摘要:在计算机发展早期,CPU的资源十分昂贵,如果一个CPU只能运行一个程序,那么当读写磁盘是CPU就只能处于空闲状态,造成了极大的浪费。从而有了 多道程序 的方式,即编译一个监控程序,当程序不需要使用CPU时,将其他在等待CPU的程序启动。该方式大大提高了CPU的利用率,但它的弊端是不分轻重缓急,有时候一个交互操作可能要等待数十分钟。 分时系统 :每个CPU运行一段时间后,就主动让出给其他CPU使用。Windows早期版本和Mac OS版本都是采用的这种分时系统来调度程序的。但是一旦有任何程序出现问题无法主动让出CPU给其它程序的话那么操作系统也没有办法,其它程序只能等待,造成死机假象。 多任务系统 :操作系统接管了所有的硬件资源,并且本身运行在一个受硬件保护的级别。所有的应用都以进程的方式运行在比操作系统更低的级别,每个进程都有自己独立的地址空间,使得进程之间的地址空间相互隔离。CPU由操作系统进行同一分配,每个进程根据进程优先级的高低都有机会获得CPU,但如果运行超过一定的时间,CPU会将资源分配给其他进程,这种CPU分配方式是抢占式,操作系统可以强制剥夺CPU资源并且分配给它认为目前最需要的进程。如果操作系统分配每个进程的时间很短,就会造成很多进程都在同时运行的假象,即所谓的宏观并行,微观串行。 什么是线程 线程(Thread),有时被称为轻量级进程(Lightweight

进程间通信方式

99封情书 提交于 2019-11-28 16:19:01
进程间通信 Inter-Process Communication,IPC 1) 匿名管道 int pipe(int fd[2]); 产生一个管道,两端各自用一个文件描述符表示,其中读端的文件描述符保存在fd[0]中,写端的文件描述符保存在fd[1]中。 只能用于父子进程间通信。在两个进程中只保留个描述符,一个保留写,另一个保留读,反之亦然。 2) 命名管道 named pipe (mkfifo) int mkfifo(const char *pathname, mode_t mode); //按指定的权限去创建管道文件 打开是不应使用O_CREAT; 打开操作会等待同时存在读写双方时才继续; 可以用于任意进程间单向通信。 3) 匿名本地网络 socketpair(AF_LOCAL, SOCK_STREAN, 0, int fd[2]); //产生一对相互连接的网络套接字,可以用于两进程间相互通信 用于fork的父子进程中通信,每个进程中只保留个套接字就好,读写都用它。 4)专业的进程间通信方式: 共享内存、消息队列、信号量 共享内存: int shmget(key_t key, size_t size, int shmflg); //创建或获取一块共享内存对象,返回对象id,同一个可以返回同一个共享内存id, 当key是IPC_PRIVATE的时候例外,总是创建一片新的共享内存

互斥锁(Lock),递归锁(Rlock),信号量(Samaphore)

久未见 提交于 2019-11-28 15:43:16
1.互斥锁:牺牲了效率,保证了数据安全,缺点:acqueire后其他进程必须等到该进程release后才能继续拿到锁,可能出现死锁情况。 2.递归锁 这个Rlock 内部有一个Lock 和counter counter是用来记录acquire的次数,可以使得资源可以被多次acquire,直到一个线程所有的 acquire都被release,其他的线程才能获得资源,同步锁和递归锁得区别:递归锁可以连续acquire多次,而互斥锁只能acquire一次 总结:Rlock可以多次acquire,每次acquire就相当于counter + 1, 只要counter 不为 0 ,别的进程就无法拿到我的锁,就是锁已经有主人了,除非等我释放了该锁,counter - 1 = 0 这个时候 其他线程才可以 拿到锁。 3.信号量 信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁区执行任务,如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群人去抢公共厕所,公共厕所有多个坑位,这意味着同一 时间可以有多个人上公共厕所,但是公共厕所容纳的人数是一定的,这便是信号量的大小 来源: https://www.cnblogs.com/jingandyuer/p/11413639.html

如何查看共享内存?

不打扰是莪最后的温柔 提交于 2019-11-28 15:36:40
查看共享内存:ipcs -m 删除共享内存:ipcrm -m shmid 查看信号量:ipcs -s 删除信号量:ipcrm -s semid 查看消息队列:ipcs -q 删除消息队列:ipcrm -q queueid 来源: https://blog.csdn.net/qq_35210580/article/details/100079818

【Python下进程同步之互斥锁、信号量、事件机制】

人盡茶涼 提交于 2019-11-28 14:52:37
原文: http://blog.gqylpy.com/gqy/229 一、锁机制: multiprocess.Lock 上篇博客中,我们 千方百计 实现了程序的异步,让多个任务同时在几个进程中并发处理,但它们之间的运行没有顺序。尽管并发编程让我们能更加充分的利用io资源,但是也给我我们带来了新问题, 多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题. 例: # 多进程抢占输出资源 from multiprocessing import Processfrom os import getpidfrom time import sleepfrom random import random def work(i): print("%s: %s is running" %(i, getpid())) sleep(random()) print("%s: %s is done" %(i, getpid())) if __name__ == '__main__': for i in range(5): p = Process(target=work, args=(i,)) p.start() 使用互斥锁维护执行顺序: # 使用锁机制维护执行顺序 from multiprocessing import Process, Lockfrom os import getpidfrom

python多任务编程---进程

和自甴很熟 提交于 2019-11-28 12:49:23
多任务编程 意义:充分利用计算机CPU的多和资源,同时处理多个应用程序任务,一次提高程序的运行效率. 实现方案:多进程,多线程 进程(process) 进程理论基础 定义:程序在计算机中的一次运行. 程序是一个可执行的文件,是静态的战友磁盘. 进程是一个动态的过程描述,占有计算机运行资源,有一定的生命周期 系统中如何产生一个进程 用户空间通过调用程序接口或者命令发起请求 操作系统接受用户请求,开始创建进程 操作系统调配计算机资源,确定进程状态等 操作系统将创建的进程提供给用户使用 进程基本概念 CPU时间片:如果一个进程占有CPU内核则称这个进程在cpu时间片上. PCB(进程控制块):在内存中开辟的一块空间,用于存放进程的基本信息,也用于系统查找识别进程 进程ID(PID):系统为每个进程分配的一个大于0的整数,作为进程ID.每个ID不重复     Linux查看进程ID:ps - aux 父子进程:系统中每一个进程(除了系统初始化进程)都有唯一的父进程,可以有0个或者多个子进程.父子进程关系便于进程管理     查看进程树: pstree 进程状态 三态 就绪态:进程具备执行条件,等待分配CPU资源 运行态:进程占有CPU时间片正在运行 等待态:进程暂时停止运行,让出CPU 五态(在三态基础上增加新建和终止) 新建: 创建一个进程,获取资源过程 终止:进程结束,释放资源过程

操作系统

六眼飞鱼酱① 提交于 2019-11-28 08:15:25
文章目录 什么是操作系统 系统调度(分进程和线程) 进程的上下文切换 进程通信 管道 共享内存 信号量 消息队列 socket 死锁 内存管理 什么是内存 相对地址 绝对地址 逻辑地址 物理地址 线性地址 为什么要内存管理 虚拟内存 什么是缓存 缓存替换算法 内存管理方式 什么是操作系统 操作系统是管理和控制计算机硬件与软件资源的计算机程序。 操作系统主要有五大功能:处理机管理(CPU)、进程管理、内存管理、设备管理和文件系统管理。 系统调度(分进程和线程) 引起进程调度的原因有以下几类: (1)正在执行的进程执行完毕。 (2)执行中的进程自己调用阻塞原语将自己阻塞起来进入睡眠状态。 (3)执行中的进程调用了 P 原语操作,从而因资源不足而阻塞;或调用 V 原语操作激活了等待资源的进程队列。 (4)在分时系统中,当一进程用完一个时间片。 (5)就绪队列中某进程的优先级变得高于当前执行进程的优先级,也将引起进程调度。 进程的上下文切换 将CPU硬件状态从一个进程换到另一个进程的过程称为上下文切换,其实就是运行环境的切换。 进程运行时,其硬件状态保存在CPU上的寄存器中。寄存器有:程序计数器、程序状态寄存器、栈指针、通用寄存器、其他控制寄存器的值 进程不运行时,这些寄存器的值保存在进程控制块中;当操作系统要运行一个新的进程时,将进程控制块中相关值送到对应的寄存器中。 进程的内存布局

ucosii使用

我怕爱的太早我们不能终老 提交于 2019-11-28 08:11:37
当需要同时跑多个任务的时候裸机显然不能很好的完成使命,这个时候我们可以给单片机上系统,创建多任务,完成复杂逻辑 一、首先移植uocii在我们的板上,根据mcu型号移植ucosii,需要做相应配置 我用的是ucoii mcu型号是stm32rct6 https://blog.csdn.net/lo_heng/article/details/79127081(移植参考网址) 二、编写任务函数并设置其堆栈大小和优先级等参数。 设置函数堆栈大小,这个需要根据函数的需求来设置,如果任务函数的局部变量多,嵌 套层数多,那么相应的堆栈就得大一些,如果栈设置小了,很可能出现的结果就是 CPU进入 HardFault,遇到这种情况,你就必须把堆栈设置大一点了。另外,有些地方还需要注意堆栈字节对齐的问题,如果任务运行出现莫名其妙的错误(比如用到 sprintf 出错),请 考虑是不是字节对齐的问题。 设置任务优先级,这个需要大家根据任务的重要性和实时性设置,记住高优先级的任务 有优先使用 CPU 的权利。 三、调用 OSInit,初始化 UCOSII,通过调用 OSTaskCreate 函数创建我们的任务。调用 OSStart,启动 UCOSII。 注意:在应用程序中经常有一些代码段必须不受任何干扰地连续运行,这样的代码段叫做临界段 (或临界区)。因此,为了使临界段在运行时不受中断所打断

共享内存

谁说我不能喝 提交于 2019-11-28 08:10:17
  共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。   采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。   默认情况下通过fork派生的子进程并不与父进程共享内存区。通过一个程序来验证,程序功能是让父子进程都给一个名为count的全局变量加1操作,程序如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/types.h> 5 #include