linux进程间通讯--信号量

1.认识信号量

        方便理解:信号量就是一个计数器。当它大于0能用,小于等于0,用不了,这个值自己给。

2.特点:

  1. 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  2. 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。(P操作:拿锁。V操作:放回锁)
  3. 每次对信号量的 PV 操作不仅限于对信号量值加 1 或 减1 ,而且可以加加减任意正整数。
  4. 支持信号量组

3.有关api:

#include <sys/sem.h>//1.创建或获取一个信号量组:若成功返回信号量级ID,失败返回-1
int semget(key_t key, int num_sems, int sem_flags);//2.对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops);//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...);

1.semget

功能:创建一个新的信号量或获取一个已经存在的信号量的键值。

返回值:成功返回信号量的标识码ID。失败返回-1;

参数:

key  为整型值,用户可以自己设定。有两种情况:

1.       键值是IPC_PRIVATE,该值通常为0,意思就是创建一个仅能被进程进程给我的信号量。

2.       键值不是IPC_PRIVATE,我们可以指定键值,例如1234;也可以一个ftok()函数来取得一个唯一的键值。

sems 表示初始化信号量的个数。比如我们要创建一个信号量,则该值为1.,创建2个就是2。

flags  :信号量的创建方式或权限。有IPC_CREAT,IPC_EXCL。

IPC_CREAT如果信号量不存在,则创建一个信号量,否则获取。

IPC_EXCL只有信号量不存在的时候,新的信号量才建立,否则就产生错误。

2.semop

//2.对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops);

该函数的主要作用是执行对一个或多个信号量的原子操作,包括P操作(sem减1)和V操作(sem加1),以实现进程间的同步与互斥。

其中,参数semid为信号量集的标识符;参数sops指向进行操作的结构体数组的首地址;参数nsops指出将要进行操作的信号的个数。

需要注意的是,信号量的值只能通过PV操作来改变。当信号量的值大于0时,表示当前有可用资源,进程可以继续执行;若信号量的值小于等于0,则表示无可用资源,进程需要暂停等待。

另外,semop函数调用成功返回0,失败返回-1。因此在使用该函数时,需要进行错误检查以确保操作的正确性。

具体参数解释:

  _semid : 信号量的标识码。也就是semget()的返回值。

 _sembuf是一个指向结构体数组的指针。

1 struct sembuf 
2 {
3     short sem_num; // 信号量组中对应的序号,0~sem_nums-1
4     short sem_op;  // 信号量值在一次操作中的改变量
5     short sem_flg; // IPC_NOWAIT, SEM_UNDO
6 }

sembuf解释:

1.em_num:  操作信号在信号集中的编号。第一个信号的编号为0;

2.sem_op : 如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。

3.semflg

IPC_NOWAIT //对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。

IPC_UNDO //程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。

_nsops:操作结构的数量,恒大于或等于1。

//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...);

3.semctl

  1. semid:表示要操作的信号量集的标识符,通常由 semget() 函数返回。
  2. semnum:表示要操作的信号量的索引号,这里设置为 0,表示对第一个信号量进行操作。
  3. cmd    命令,表示要进行的操作

       下面列出的这些命令来源于百度!

        参数cmd中可以使用的命令如下:

  •         IPC_STAT读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
  •         IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
  •         IPC_RMID将信号量集从内存中删除
  •         GETALL用于读取信号量集中的所有信号量的值。
  •         GETNCNT返回正在等待资源的进程数目。
  •         GETPID返回最后一个执行semop操作的进程的PID。
  •         GETVAL返回信号量集中的一个单个的信号量的值。
  •         GETZCNT返回这在等待完全空闲的资源的进程数目。
  •         SETALL设置信号量集中的所有的信号量的值。
  •         SETVAL设置信号量集中的一个单独的信号量的值。
    通常为标黄的命令

如果有第四个参数,它通常是一个union semum结构,定义如下:

union semun {int val;          // 用于SETVAL命令,表示要设置的信号量的值。struct semid_ds *buf; // 用于IPC_STAT、IPC_SET命令,指向一个semid_ds结构体的指针。unsigned short *array; // 用于GETALL、SETALL命令,指向一个无符号短整型数组的指针。struct seminfo *__buf; // 用于IPC_INFO命令,指向一个seminfo结构体的指针(Linux-specific)。
};

前两个参数与前面一个函数中的一样,command通常是下面两个值中的其中一个
SETVAL:用来把信号量初始化为一个已知的值。这个值通过union semun中的val成员设置,其作用是在信号量第一次使用前对它进行设置。

IPC_RMID:用于删除一个已经无需继续使用的信号量标识符。

4.代码例子

使用信号量实现父子进程先后进行。

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>/*
//1.创建或获取一个信号量组:若成功返回信号量级ID,失败返回-1
int semget(key_t key, int num_sems, int sem_flags);//2.对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops);//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...);*/// union for semctl to initialize
union semun {int val;          // 用于SETVAL命令,表示要设置的信号量的值。struct semid_ds *buf; // 用于IPC_STAT、IPC_SET命令,指向一个semid_ds结构体的指针。unsigned short *array; // 用于GETALL、SETALL命令,指向一个无符号短整型数组的指针。struct seminfo *__buf; // 用于IPC_INFO命令,指向一个seminfo结构体的指针(Linux-specific)。
};//initialize sem to 0int init_sem(int sem_id,int value){union semun tmp;tmp.val = value;if(semctl(sem_id,0,SETVAL,tmp)==-1){perror("init sem erro");return -1;}return 0;
}//p operate
// if sem == 1,get message to sem =-1
//if sem == 0, process waitint sem_p(int sem_id){struct sembuf pbuf;pbuf.sem_num  = 0;pbuf.sem_op   = -1;pbuf.sem_flg  = SEM_UNDO;if(semop(sem_id,&pbuf,1) == -1){perror("p operate error");return -1;}return 0;
}//v operate
//sem >1 operateint sem_v(int sem_id){struct sembuf vbuf;vbuf.sem_num  = 0;vbuf.sem_op   = 1;//v operatevbuf.sem_flg  = SEM_UNDO;if(semop(sem_id,&vbuf,1) == -1){perror("v operate error");return -1;}return 0;
}//delete semint del_sem(int sem_id){union semun tmp;if(semctl(sem_id,0,IPC_RMID) == -1){perror("delete sem error");return -1;}return 0;
}int main()
{int  sem_id;key_t key;pid_t pid;//get key numif((key = ftok(".",11))<0){perror("semget error");exit(-1);}//build sem only 1if(sem_id = semget(key,1,IPC_CREAT|0700)==-1){perror("semget error");exit(-1);}//initilizeinit_sem(sem_id,0);//father&child processif((pid = fork())== -1){perror("fork errror");exit(-1);}else if(pid == 0){   //child processsleep(1);printf("process from child pid :%d\n",getpid());sem_v(sem_id);//release resource &put tne lock}else {  //father processsem_p(sem_id);printf("father process pid:%d\n",getpid());sem_v(sem_id);del_sem(sem_id);}return 0;
}

突然意识到结构体和联合体是不同的,请看文章:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/109025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

英特尔 SGX 技术概述

目录 介绍概述指示结构Memory安全区页面缓存Enclave Page Cache &#xff08;EPC&#xff09;安全区页面缓存映射Enclave Page Cache Map (EPCM) Memory ManagementStructures页面信息Page Information (PAGEINFO)安全信息Security Information (SECINFO)分页加密元数据Paging …

大型公共建筑能耗监测与信息管理系统研究及产品选型

摘要&#xff1a;文章通过阐述大型公共建筑能耗现状&#xff0c;突出大型公共建筑实施节能监管的必要性&#xff0c;并在系统总结运用技术手段实施建筑能耗监测的基础上&#xff0c;介绍了江苏省建筑能耗监测系统研究过程中的技术创新和应用情况。 关键词&#xff1a;公共建筑…

Python 环境构建最佳实践:联合使用 Mamba + Conda + PIP

此前,我们单独介绍过 PIP 和 Conda,在后续的实际应用中,还是遇到了不少 Python 环境构建的问题,特别是在 Windows 系统上,最突出的表现是:虽然PIP的包依赖解析和下载都很快,但在 Windows 上经常会因为缺失底层依赖的程序库(例如某些dll文件)而导致 Python 程序启动时报…

【数据挖掘】数据挖掘、关联分析、分类预测、决策树、聚类、类神经网络与罗吉斯回归

目录 一、简介二、关于数据挖掘的经典故事和案例2.1 正在影响中国管理的10大技术2.2 从数字中能够得到什么&#xff1f;2.3 一个网络流传的笑话(转述)2.4 啤酒与尿布2.5 网上书店关联销售的案例2.6 数据挖掘在企业中的应用2.7 交叉销售 三、数据挖掘入门3.1 什么激发了数据挖掘…

深度丨券商如何落地基于客户旅程编排的陪伴式服务?

金融行业的本质是服务行业。现阶段&#xff0c;传统券商为客户提供的通道服务高度依赖于证监会颁发的牌照&#xff0c;难以通过差异化的服务给客户提供价值。而伴随着引流开户成本高企&#xff0c;流量红利消失&#xff0c;金融行业步入存量竞争的时代&#xff0c;券商必须通过…

# 鸿蒙ArkTS Api9 AES ECB 加密

鸿蒙ArkTS Api9 AES ECB 加密 由于鸿蒙ArkTS是javascript编写的&#xff0c;因此总是感觉会被抓包破解了&#xff0c;不过这个问题通过提了个工单问了一下&#xff0c;目前鸿蒙编译完成之后的包是无法获取到其内部代码的。因此就能够放心的把加密的密钥给扔在里边了。 所以研究…

DAY 1 QT 创建QQ界面

#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//创建一个窗口&#xff0c;改变窗口标签名和窗口标签图标this -> resize(640,500);//设置窗口界面大小this -> setWindowTitle("QQ登录");//设置窗口标题this -> s…

文件传输软件的挑战与发展趋势

无论是在教育、医疗、金融、媒体、政府等行业&#xff0c;还是在个人生活和工作中&#xff0c;文件传输软件都有着广泛的应用价值和意义。然而&#xff0c;随着信息技术的发展和数据量的增长&#xff0c;文件传输软件也面临着一些挑战和问题&#xff0c;同时也有着一些发展趋势…

weapp-tailwindcss for uni-app 样式条件编译语法插件

weapp-tailwindcss for uni-app 样式条件编译语法插件 版本需求 2.10.0 weapp-tailwindcss for uni-app 样式条件编译语法插件 这是什么玩意?如何使用 tailwind.config.js 注册postcss 插件注册 uni-app vite vue3uni-app vue2 配置完成 配置项 这是什么玩意? 在 uni-app …

如何在小程序中设置页面显示的文字

不同商家&#xff0c;对于小程序有不同的要求。所以&#xff0c;小程序应该支持商家在后台灵活配置小程序各个页面的文字显示。下面具体介绍如何显示各个页面的文字。 朋友圈分享图文字&#xff1a;会显示在朋友圈海报顶部 升级会员提示&#xff1a;对于普通会员&#xff0c;在…

Ansible定义命令行、主机/主机组、playbook等变量,注册变量和vars_prompt的用法示例

目录 一.Ansible定义变量 1.用途 2.定义规则 3.变量优先级 二.命令行定义变量 三.定义主机和主机组变量 1.主机变量 &#xff08;1&#xff09;内置主机变量 &#xff08;2&#xff09;简单示例 2.主机组变量 四.定义playbook变量 1.通过vars表示定义变量&#xff…

redis问题汇总

文章目录 一.redis的优点二.redis的数据结构三.redis分布式锁是怎么回事&#xff1f;四.redis里面有1亿个key&#xff0c;其中有10w个key是以某个固定前缀开头的&#xff0c;如何将他们全部找出来&#xff1f;五.如何使用redis作异步队列六.如果有大量的key需要设置同一过期时间…

C++ —— Tinyxml2在Vs2017下相关使用2(较文1更复杂,附源码)

相关链接 C —— Tinyxml2在Vs2017下相关使用1&#xff08;附源码&#xff09; tinyxml2简介 TinyXML2是一个简单&#xff0c;小巧&#xff0c;高效&#xff0c;CXML解析器&#xff0c;可以很容易地集成到其他程序中。TinyXML-2解析一个XML文档&#xff0c;并从中构建一个 可以…

基于Scrapyd与Gerapy部署scrapy爬虫方案【可用于分布式爬虫部署】

scrapyd部署爬虫 Scrapyd 是一个基于 Scrapy 的开源项目&#xff0c;它提供了一个简单的方式来部署、运行和监控 Scrapy 爬虫。它是一个用于集成 Scrapy 爬虫到分布式架构中的工具&#xff0c;允许您在分布式环境中运行爬虫&#xff0c;并提供了一组 Web API&#xff0c;用于管…

大模型LLM相关面试题整理-训练集-训练经验-微调

3 大模型&#xff08;LLMs&#xff09;微调 3.1 如果想要在某个模型基础上做全参数微调&#xff0c;究竟需要多少显存&#xff1f; 要确定全参数微调所需的显存量&#xff0c;需要考虑以下几个因素&#xff1a; 模型的大小&#xff1a;模型的大小是指模型参数的数量。通常&…

Spring()

一、导学 二、 1.入门程序 spring快照版本是最新的版本&#xff0c;未发布。需要用到<repository></> 下面这个不需要配置仓库&#xff0c;直接写在依赖中就行 引入spring相关依赖 <?xml version"1.0" encoding"UTF-8"?> <proje…

(Python) Python中三种时间格式的转换方法

1. 时间元组 1.1. 时间元组和时间戳的互相转化 import time,datetime # 获取当前时间的时间元组 t time.localtime() print(t) # 时间元组转时间戳 timestamp time.mktime(t) print(timestamp) # time.struct_time(tm_year2019, tm_mon10, tm_mday23, tm_hour23, tm_min15,…

中国移动集采120万部,助推国产5G赶超iPhone15

近期媒体纷纷传出消息指中国移动将大规模集采&#xff0c;预计将采购国产5G手机120万台&#xff0c;加上另外两家运营商的集采数量&#xff0c;估计集采数量可能达到300万部&#xff0c;如此将有助于它在国内高端手机市场赶超苹果。 国产5G手机在8月底突然上市&#xff0c;获益…

python+pytest接口自动化 —— 参数关联

什么是参数关联&#xff1f; 参数关联&#xff0c;也叫接口关联&#xff0c;即接口之间存在参数的联系或依赖。在完成某一功能业务时&#xff0c;有时需要按顺序请求多个接口&#xff0c;此时在某些接口之间可能会存在关联关系。 比如&#xff1a;B接口的某个或某些请求参数是…

攻防演练蓝队|Windows应急响应入侵排查

文章目录 日志分析web日志windows系统日志 文件排查进程排查新增、隐藏账号排查启动项/服务/计划任务排查工具 日志分析 web日志 dirpro扫描目录&#xff0c;sqlmap扫描dvwa Python dirpro -u http://192.168.52.129 -b sqlmap -u "http://192.168.52.129/dvwa/vulnera…