linux信号量

Linux -- 进程间通信之信号量

為{幸葍}努か 提交于 2019-12-05 15:59:24
基本概念简述 多个线程同时访问一个共享数据,很可能造成恶劣的后果;为了保证数据访问资源的正确性和安全性,需要对线程进行"同步" (Linux下所有的执行实体都称为任务(task),每个任务类似于单线程的进程,共享了同一个内存空间的多个任务构成了一个进程) 同步 指在一个线程对数据访问未结束的时候,其他线程不得访问同一个数据,将对数据的访问原子化 原子操作 不可分割,不会被线程调度打断的操作 (一个程序在运行的过程中可能被优先级更高的线程中断,而有些操作是不可中断的,不然会出现无法还原的后果,这时候操作系统就需要原子操作) 线程同步 同步最常用的方式"锁",每一个线程访问数据或资源前首先要获取锁,并在访问结束后释放锁;在锁被占用时试图获取锁,线程会进入等待,直到锁重新可用 二元信号量是最简单的一种锁,适合被一个线程独占访问的资源。它只有两种状态,占用和非占用;当一个线程获取锁后,其他线程试图获取锁将进入等待,直到该锁被释放。 互斥量类似于二元信号量,资源同时只允许一个线程访问,不同的是信号量在整个系统中允许任何线程获取并释放,即信号量可以被系统中一个线程获取,然后由另一个线程释放它;而互斥锁要求哪个线程获取互斥量,这个线程就要负责释放这个锁,其他线程释放该互斥量是无效的 临界资源 一次仅允许一个进程访问的资源称为临界资源,通常用互斥量控制临界资源的访问 P(测试)/ V(增加)操作

并发和竞态

十年热恋 提交于 2019-12-04 18:26:22
(一)基本概念 对并发的管理是操作系统编程领域中的核心问题之一。 设备驱动程序开发者必须在开始设计时就考虑到并发因素,并对内核提供的并发管理机制有深刻的认识。 竞态:竞争状态; 引发竞态的原因是:并发式访问同一共享资源: ①多线程并发访问; ②抢占式并发访问; ③中断程序并发访问; ④SMP(Symmetric Multi-Processing)核间并发访问; 竞态造成的影响:处于竞态中的任务,所获得资源与预期不符,从而产生非预期的结果。 设计驱动程序的规则: ①尽可能避免资源共享,最明显的应用就是避免使用全局变量; ②在单个执行线程之外共享硬件或者软件资源的任何时候,必须显式地管理对该资源的访问,确保一次只有一个执行线程可操作共享资源; ③当内核代码创建了一个可能和内核的其他部分共享的对象时,该对象必须在还有其他组件引用自己时保持存在并正确工作;在对象还不能正确工作时,不能将其对内核可用; (二)信号量和互斥体 信号量分为:计数型信号量和二值信号量,二值信号量也称作互斥体。 目的:建立临界区,确保在任意时刻,临界区只被一个任务访问。 一个信号量的本质就是一个整数,它和一对函数联合使用,这对函数通常被称为P和V。 Linux内核中几乎所有的信号量均用户互斥。(因此,只要知道,计数型信号量的原理与停车场相似即可。) 如果在拥有一个信号量时发生错误

Linux命令:ipcs/ipcrm命令

断了今生、忘了曾经 提交于 2019-12-04 15:22:44
ipcs/ipcrm命令 是linux/uinx上提供关于一些进程间通信方式的信息,包括共享内存,消息队列,信号 多进程间通信常用的技术手段包括共享内存、消息队列、信号量等等,Linux系统下自带的ipcs命令是一个极好的工具,可以帮助我们查看当前系统下以上三项的使用情况,从而利于定位多进程通信中出现的通信问题。 ipcs -a命令可以查看当前使用的共享内存、消息队列及信号量所有信息,对于该选项对应的结果,介绍以下几个部分: 1、信号量在创建时分信号量集和信号量的概念,该命令的查询结果中,Semaphore Arrays下面每一行代表一个信号量集,其中perms对应信号量集的权限,nsems对应信号量集中信号量的个数,对于信号量集的创建方法可以查询semctl相关的函数使用方法。 2、对于消息队列Message Queues而言,可以看到msqid对应创建队列时得到的id值,从messages中可以看到当前队列中存在的消息个数,从used_bytes中可以看到当前所有消息占用的字节数,所以单个消息的字节数则为总字节数除以消息数,同时如果消息个数不为零则说明消息队列中的消息没有得到及时处理,可以据此判断是否存在队列阻塞的风险。 1. 命令格式   ipcs [resource-option] [output-format]   ipcs [resource-option] -i id

Linux 多线程编程(实现生产者消费者模型)

我是研究僧i 提交于 2019-12-04 01:47:08
Linux 多线程编程 线程分类 线程按照其调度者可以分为用户级线程和内核级线程两种。 内核级线程 在一个系统上实现线程模型的方式有好几种,因内核和用户空间提供的支持而有一定程度的级别差异。最简单的模型是在内核为线程提供了本地支持的情况,每个内核线程直接转换成用户空间的线程。这种模型称为“1:1线程模型(threading)”,因为内核提供的线程和用户的线程的数量是1:1。该模型也称为“内核级线程模型(kernel-level threading)”,因为内核是系统线程模型的核心。 Linux 中的线程就是“1:1线程模型”。在linux内核中只是简单地将线程实现成能够共享资源的进程。线程库通过系统调用 clone() 创建一个新的线程,返回的“进程”直接作为用户空间的线程。也就是说,在Linux上,用户调用线程和内核调用线程基本一致。 Linux的线程实现是在核外进行的,核内提供的是创建进程的接口do_fork()。内核提供了两个系统调用clone()和fork(),最终都用不同的参数调用do_fork()核内API。当然,要想实现线程,没有核心对多进程(其实是轻量级进程)共享数据段的支持是不行的,因此,do_fork()提供了很多参数,包括CLONE_VM(共享内存空间)、CLONE_FS(共享文件系统信息)、 CLONE_FILES(共享文件描述符表)、CLONE

进程之间的通信方式

匿名 (未验证) 提交于 2019-12-02 23:52:01
进程之间的通信方式有管道、消息队列、共享内存、信号量和Socket。 管道 来看一条Linux的指令: netstat - tulnp | grep 8080 学过Linux命名的估计都懂得这条指令的含义,其中的【|】就是管道的意思,作用是把前一条命令的输出作为后一条命令的输入。在这里就是把netstat -tulnp的输出结果作为grep 8080这条指令的输入。如果两个进程要进行通信的话,就可以用这种管道进行通信了,并且这种通信方式是单向的,只能把第一个命令的输出作为第二个命名的输入,如果进程之间想要互相通信的话,就需要创建两个管道。 另外我们可以知道,这条竖线是没有名字的,我们把这种通信方式称之为匿名管道。既然有匿名管道,那就意味着有命名管道,下面我们来创建一个命名管道: mkfifo test 这条命令创建了一个名字为test的命名管道。 接下来我们用一个进程向这个管道里面写数据,然后会有另外一个进程把里面的数据读出来。 echo "this is a pipe" > test // 写入数据 这个时候管道的内容没有被读出来的话,那么这个命令就会一直停在这里,只有当另一个进程把test里面的内容读出来的时候,这条命令才会结束。 cat < test // 读数据 我们可以看到,test里面的数据被读出来了,上一条命令也就执行结束了。 从上面的例子可以看出

Linux线程间同步的几种方式

匿名 (未验证) 提交于 2019-12-02 21:56:30
信号量强调的是线程(或进程)间的同步:“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在sem_wait的时候,就阻塞在那里)。当信号量为单值信号量时,也可以完成一个资源的互斥访问。信号量测重于访问者对资源的有序访问,在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。 可以用于不同进程间或多线程间的互斥与同步 创建打开有名信号量 sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); //成功返回信号量指针;失败返回SEM_FAILED,设置errno name是文件路径名,但不能写成/tmp/a.sem这样的形式,因为在linux下,sem都是在/dev/shm目录下,可写成"/mysem"或"mysem",创建出来的文件都是"/dev/shm/sem.mysem",mode设置为0666,value设置为信号量的初始值.所需信号灯等已存在条件下指定O_CREAT|O_EXCL却是个错误。 关闭信号量,进程终止时,会调用它 int sem_close(sem

Linux信号量动作和说明列表

匿名 (未验证) 提交于 2019-12-02 21:56:30
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010214802/article/details/90572691 ctrl退出指令 Ctrl-C 发送 INT signal (SIGINT),通常导致进程结束 Ctrl-Z 发送 TSTP signal (SIGTSTP),通常导致进程挂起(suspend) Ctrl-\ 发送 QUIT signal (SIGQUIT),通常导致进程结束 和 dump core 举例:kill -9指令 kill -9 pid 会发送 SIGKILL信号给进程 信号列表 在POSIX.1-1990(可移植操作系统接口Portable Operating System Interface)标准中定义的信号列表 信号 值 动作 说明 SIGHUP 1 Term 终端控制进程结束(终端连接断开) SIGINT 2 Term 用户发送INTR字符(Ctrl+C)触发 SIGQUIT 3 Core 用户发送QUIT字符(Ctrl+/)触发 SIGILL 4 Core 非法指令(程序错误、试图执行数据段、栈溢出等) SIGABRT 6 Core 调用abort函数触发 SIGFPE 8 Core 算术运行错误(浮点运算错误、除数为零等) SIGKILL 9 Term 无条件结束程序(不能被捕获、阻塞或忽略

Linux进程间通信 --- IPC机制(转)

余生颓废 提交于 2019-12-02 12:27:58
在linux下的多个进程间的通信机制叫做IPC(Inter-Process Communication),它是多个进程之间相互沟通的一种方法。在linux下有多种进程间通信的方法:半双工管道、命名管道、消息队列、信号、信号量、共享内存、内存映射文件,套接字等等。使用这些机制可以为linux下的网络服务器开发提供灵活而又坚固的框架。 1. 管道 (PIPE) 管道实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。 管道的特点: 1、管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 2、只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。比如fork或exec创建的新进程,在使用exec创建新进程时,需要将管道的文件描述符作为参数传递给exec创建的新进程。当父进程与使用fork创建的子进程直接通信时,发送数据的进程关闭读端,接受数据的进程关闭写端。 3、单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。 4、数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾

互斥那点事儿(下)

纵饮孤独 提交于 2019-12-01 22:12:45
“我找到好办法了!” 没有想到,说话的人竟然是磁盘! 进程调度器瑟瑟的说:“你有方法?还是算了吧,我怕用你的方法操作系统要乱套了。” 磁盘委屈的道:“不就是刚刚冤枉你了吗,这么小气干什么!再说了,这个方法不是我想出来的,是我从文件里找到的。” 操作系统挑了挑眉毛:“哦?你找到什么文件了,让大家也瞅瞅?” 磁盘嗡嗡的转起来,很快就把文件取出来了。 “当当当当~ 这可是大师 Dijkstra 的论文,他引入了一个全新的变量类型—— 信号量 (semaphore)。然后还为信号量设置了两种操作, P (proberen,检测) 和 V (verhogen,增量) 。” ”说清楚点啊,信号量是怎么个用法啊?“进程急切的问道。 “别急,让我接着看。。。Dijkstra 提出, P 操作是检测信号量是否为正值,如果不是,就阻塞调用进程。 V 操作能唤醒一个阻塞进程,让他恢复执行 。具体点的话就是这样: “ // S 为信号量 P(s): { S = S - 1 if (S < 0) { 调用该 P 操作的进程阻塞,并插入相应的阻塞队列; } } // S 为信号量 V(s): { S = S + 1 if (S <= 0) { 从等待信号量 S 的阻塞队列里唤醒一个进程; } } 内存仔细看了代码,说:”这个实现也要求是 原子操作 诶,Dijkstra 这个方法很有趣啊。“ 进程蒙圈了:

进程通信4--信号量(Semaphore)

时光怂恿深爱的人放手 提交于 2019-11-30 19:47:05
信号量是什么? (1) 信号量本质上是一个具有原子性的计数器 ,用来描述临界资源的,不能用全局变量count加加减减替换(因为他 没有原子性 )。 (2)信号量以保护临界资源为目的,但他本身也是个临界资源;他控制多个进程对共享资源的访问,通常描述临界资源当中,临界资源的数量,常常被当做锁来使用,防止一个进程访问另外一个进程正在使用的资源 (3)其中最简单的信号量=1,也叫做 二元信号量(互斥锁) ,可控制单个资源,只能取0和1;信号量>=2为 多元信号量 只要理理解上面三句话,应该结合代码理解就不难了。 代码实现相关函数: # include <sys/types.h> # include <sys/ipc.h> key_t ftok ( const char * pathname , int id ) //pathname:路径名 id:项目id,非0整数(只有低8位有效) //2.semget函数 int semget ( key_t key , int nsems , int semflg ) ; //参数:key-->信号集的名字 //nsems:信号集中信号量的个数 //semflg:由九个权限构成,用法和创建文件时使用的mode模式一样 //返回值:成功返回一个非负整数,即该信号集的标识码;失败返回-1 创建成功后,Linux下通过ipcs