linux信号量与PV操作知识点总结

简介: linux信号量与PV操作知识点总结

信号量

信号量(semaphore) 与已经介绍过的 IPC 结构不同,它是一个计数器,信号量用于实现进程间的与斥与同步,而不是用于存储进程间通信数据。

1、特点

(1)信号量用于进程间同步,若要在进程间传递数据需要结合共享内存

(2)信号量基于操作系统的 PV 操作,程序对信号量的操作都是原了操作。

(3)每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数

(4)支持信号量组

2、原型

最简单的信号量是只能取 0和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore) 。而可以取多个正整数的信号量被称为通用信号量。

Linux 下的信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作。


头文件:


19d15dc10d764baf957706773cc7d246_1483866c5f8b4b539ff1993d41db3952.png


1 #include <sys/sem.h>

2 // 创建或获取一个信号量组: 若成功返回信号量集ID,失败返回-1


3 int semget(key_t key, int nsems, int semflg);


4 // 对信号量组进行操作,改变信号量的值: 成功返回0,失败返回-1


5 int semop(int semid, struct sembuf *sops, unsigned nsops);

6 // 控制信号量的相关信息

7 int semctl(int semid, int semnum, int cmd, ...);


PV操作(P可看作拿锁,V看作放回锁)


PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下:


   P(S):①将信号量S的值减1,即S=S-1;                                                            

          ②如果S>=0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。

   V(S):①将信号量S的值加1,即S=S+1;                                                          

          ②如果S>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。

利用信号量和PV操作实现进程互斥的一般模型是:



   进程P1              进程P2           ……          进程Pn

   ……                  ……                           ……

   P(S);              P(S);                         P(S);

   临界区;             临界区;                        临界区;

   V(S);              V(S);                        V(S);

   ……                  ……            ……           ……



使用PV操作实现进程互斥时应该注意的是:


   (1)每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。

   (2)P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。

   (3)互斥信号量的初值一般为1。



临界资源(临界区)


多道程序系统中存在许多进程,它们共享各和资源,然而有很多资源一次只能供一个进程使用。一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如输入机、打印机、磁带机等。


示例:fork一个进程不知道父进程还是子进程先运行(都有可能),那么我们可以通过信号量与PV操作来控制让子进程先运行

编译结果:

代码示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//int semget(key_t key, int nsems, int semflg);
//int semctl(int semid, int semnum, int cmd, ...);
//int semop(int semid, struct sembuf *sops, unsigned nsops);
 
union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
};
 
void pGetKey(int id)
{
    struct sembuf set;
 
    set.sem_num = 0;
    set.sem_op = -1;
    set.sem_flg=SEM_UNDO;
 
    semop(id,  &set ,1);
    printf("getkey\n");
}
 
void vPutBackKey(int id)
{
    struct sembuf set;
 
    set.sem_num = 0;
    set.sem_op = 1;
    set.sem_flg=SEM_UNDO;
 
    semop(id,  &set ,1);
    printf("put back the key\n");
}
 
int main(int argc, char const *argv[])
{
    key_t key;
    int semid;
 
    key = ftok(".",2);
                       //信号量集合中有一个信号量  
    semid = semget(key, 1, IPC_CREAT|0666);//获取/创建信号量
 
    union semun initsem;
    initsem.val = 0;
                  //操作第0个信号量   
    semctl(semid, 0, SETVAL, initsem);//初始化信号量
                  //SETVAL设置信号量的值,设置为inisem
                  
                  
    int pid = fork();
    if(pid > 0){
        //去拿锁
    pGetKey(semid);
        printf("this is father\n");
    vPutBackKey(semid);
        //锁放回去
    semctl(semid,0,IPC_RMID);
    }
    else if(pid == 0){
        printf("this is child\n");
    vPutBackKey(semid);
    }else{
 
        printf("fork error\n");
    }            
 
 
    return 0;
}
 
 
相关文章
|
3月前
|
Linux
|
4月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
188 3
|
5月前
|
网络协议 Linux 网络安全
入职必会-开发环境搭建39-Linux常用操作-Linux防火墙操作
在CentOS 7中,新引入了firewalld服务(防火墙),取代了CentOS 6之前的iptables服务(防火墙)。
入职必会-开发环境搭建39-Linux常用操作-Linux防火墙操作
|
5月前
|
存储 运维 Linux
Linux磁盘精准缩容:操作详解与技巧
在Linux系统管理中,有效的磁盘空间优化对于维护系统性能至关重要。本文将深入探讨如何在Linux环境下安全地进行磁盘缩容,帮助你合理调整存储资源,确保系统高效运行。跟随本篇的步骤,一起优化你的Linux系统磁盘空间!
Linux磁盘精准缩容:操作详解与技巧
|
3月前
|
Linux
linux内核 —— 读写信号量实验
linux内核 —— 读写信号量实验
|
4月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
80 0
|
4月前
|
关系型数据库 Linux 数据库
linux设置信号量系统参数
linux设置信号量系统参数
|
5月前
|
Linux
【Linux】生产者消费者模型——环形队列RingQueue(信号量)
【Linux】生产者消费者模型——环形队列RingQueue(信号量)
55 0
|
5月前
|
消息中间件 Linux
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(下)
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(下)
78 0
|
5月前
|
消息中间件 存储 Linux
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(上)
【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)(上)
88 0