共 1 篇文章

标签:Linux下多进程间sem的原理和应用 (linux 多进程间sem)

Linux下多进程间sem的原理和应用 (linux 多进程间sem)

Linux操作系统是一个非常强大的操作系统,它具有非常多的优秀特性和功能。其中,多进程间sem是Linux操作系统的一个重要功能。本文将讨论。 一、sem的定义 sem是LINUX内核中的一种基本信号量,用于进程之间进行同步和互斥的工具。Linux操作系统中用信号量来实现进程间的同步互斥,sem是一种抽象数据类型,表示一组计数器,使用时通过系统调用操作sem,它提供了两种基本操作:P(sv)和V(sv),用于请求和释放资源、锁定和解锁。 二、sem的组成 期中,sem定义如下: struct sem{ int semval; //semaphore value int sempid; //PID of the last process that performed a semaphore key_t semkey; //unique key by which a semaphore is referred }; sem由下列5个部分组成: 1、semaphore value,代表着信号量的值,表示当前可用的资源的数量; 2、last process semaphore pid,最近一次操作信号量的进程的pid,是原子变量,用以保证多个进程访问sem的正确性; 3、unique key,唯一标识sem的符号名; 4、adjustment,sem的调整量,P操作的参数; 5、wt queue,信号量的等待队列,当信号量未满足P操作要求时,要挂起在等待队列上,V操作释放资源后会唤醒等待在等待队列上的进程。 三、sem的使用 在Linux中,可以通过semget()函数获取信号量,它的定义如下: #include #include #include typedef int semid_t; extern semid_t semget(key_t key, int num, int flags); 主要有以下参数: key:标识着信号量的关键字,可以唯一标志一个信号量; num:表示要创建的信号量的数目; flags:是一个选项参数,可以指定创建新的信号量,还是获取已经存在的信号量。 通过semget()函数获取到信号量的标志符后,可以使用semctl()系统调用函数对信号量进行操作,semctl()的定义如下: extern int semctl(int semid, int num, int cmd,union semun arg); 其中,参数semid是由semget()函数返回的信号量标志符,参数cmd是要执行的操作,参数arg是一个共用体类型的指针,它根据cmd来进行不同的操作。semctl()函数的主要操作如下: 1、SETVAL:用来初始化信号量的值; 2、GETVAL:用来获取信号量的值; 3、IPC_RMID:用来删除信号量。 由于sem存在于内核中,操作sem的系统调用影响效率,因此,针对不同应用场景可通过不同的操作模式尽量减小对sem的操作。 四、sem在进程间同步互斥中的应用 1、互斥访问共享资源 在进程间共享同一资源时,要保证该资源不会被多个进程同时访问,可以通过P(sv)和V(sv)操作来实现。 while(1){ P(sem_id); if(共享资源_空闲){ 访问共享资源; V(sem_id); break; } V(sem_id); } 2、进程间并发控制 进程间并发控制是指多个进程都对同一资源进行处理时,它们相互合作、竞争,互相影响。通过设置信号量,可实现对进程间的并发进行控制。 3、防止死锁 死锁是指两个或多个进程在执行过程中,因争夺资源而造成一种互相等待的现象,若无外力作用,将无法继续执行下去。当进程需要访问多个资源时,通过设置信号量,就可以在访问一个资源后,才能通过P(sv)访问下一个资源,防止死锁的发生。 相关问题拓展阅读: 进程间通信方式 进程间通信方式 在操作系统中,一个进程可以理解为是关于计算机资源的一次运行活动,其就是一个正在执行的程序的实例。从概念上蚂州来说,一个进程拥有它自己的虚拟CPU和虚拟地址空间,任何一个进程对于彼此而言都是相互独立的,这也引入了一个问题 —— 如何让进程之间互相通信? 由于进程之间是互相独立的,没有任何手段直接通信,因此我们需要借助操作系统来辅助它们。举个通俗的例子,假如A与B之间是独立的,不能彼此联系,如果它们想要通信的话可以借助第三方C,比如A将信息交给C,C再将信息转交给B —— 这就是进程间通信的主要思想 —— 共享资源。 这里要解决的一个重要的问题就是如何避免竞争,即避免多个进程同时访问临界区的资源。 共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。 你可能会想到,我直接创建一个文件,然后进程不就都可以访问了? 是的,但这个方法有几个缺陷: Linux下采用共享内存的方式来使进程完成对共享资源的访问,它将磁盘文件复制到内存,并创建虚拟地址到该内存的映射,就好像该资源本来就在进程空间之中,此后我们就可以像操作本地变量一样去操作它们了,实际的写入磁盘将由系统选择更佳方式完成,例如操作系统可能会批量处理加排序,从而液帆大大提高IO速度。 如同上图一样,进程将共享内存映射到自己的虚拟地址空间中,进程访问共享进程就好像在访问自己的虚拟内存一样,速度是非常快的。 共享内存的模型应该是比较好理解的:在物理内存中创建一个共享资源文件,进程将该共享内存绑定到自己的虚拟内存之中。 这里要解决的一个问题是如何将同一块共享内存绑定到自己的虚拟内存中,要知道在不同进程中使用 malloc 函数是会顺序分配空闲内存,而不会分配同一块内存,那么要如何去解决这个问题呢? Linux操作系统已经想办法帮我们解决了这个问题,在 #include...

技术分享