Linux--信号量共享内存

2023-11-17

1.基础知识:

(1)共享内存是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间的数据传递不再涉及内核,即进程不再通过执行进入内核的系统调用来传递彼此的数据。

(2)共享内存的生命周期随内核。

(3)注意:共享内存未提供任何保护资源,即共享内存自身没有同步与互斥机制,但它是临界资源,所以我们需要利用其它机制来保证数据的正确性,Linux下就可以用信号量达到同步的目的。

(4)linux共享内存有两种方式(本文主要介绍shmget方式):

                1)mmap方式,适用于父子进程之间,创建的内存非常大时;

                2)shmget方式,适用于同一台电脑上不同进程之间,创建的内存相对较小。

(5)进程间利用共享内存实现消息队列的基本原理如下图

 2.相关函数

1.semget

1.函数原型

2.函数功能

创建或者获取一个已经存在的信号量;

如果为全新创建,也就是不知道是否有人创建过,IPC_CREATE|IPC_EXCEL,就是如果没

有则创建 , 如果有则创建失败 ;

3.参数

key:两个进程使用相同的key,就可以使用同一个信号量;

nsems:创建几个信号量;

semflg:标志位;如果为创建:IPC_CREAT;

4.返回值

成功返回一个非负整数即该信号集的标识码;失败返回-1

2.semop

1.函数原型

2.函数功能

对信号量进行改变,P操作或者V操作;

3.参数

semid:信号量的id,也就是刚才semget的返回值;说明对哪个信号量进行操作;

sops:结构体指针,指向sembuf的结构体指针,sembuf结构体有三个成员变量:sem_num

示信号量的编号 ( 即指定信号量集中的信号量下标 );

nsops:表示是p还是v操作;1v操作 (1),-1p操作(1);sem_flg为标志位;

4.返回值

成功返回0;失败返回-1

5.说明

unsigned short sem_num;  /* semaphore number */第几个信号量
short          sem_op;   /* semaphore operation */p(-1)操作还是v操作(+1)
short          sem_flg;  /* operation flags */标志位

3.semctl

1.函数原型

**注意**:联合体semun,这个联合体需要自己定义; 

2.函数功能

控制信号量集 对信号量进行控制:初始化/删除信号量

3.参数

semid:信号量id;  由semget函数返回的信号量集标识码

semnum:信号量编号信号量集中信号量的序号

cmd:命令:SETVAL:初始化信号量; IPC_RMID:删除信号量将要采取的动作(有三个可取值)

4.返回值

成功返回0,失败返回-1

3.思路:

4.代码

1. sem.h

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/sem.h>

union semun
{
    int val;
};

void sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destroy();

2.sem.c

#include "sem.h"
#define  SEM_NUM  2
static int semid = -1;
void sem_init()
{
    semid = semget((key_t)1234,SEM_NUM,IPC_CREAT|IPC_EXCL|0600);//全新创建
    if (semid == -1 )
    {
        semid = semget((key_t)1234,SEM_NUM,0600);
        if ( semid == -1)
        {
            printf("semget err\n");
            return;
        }
    }
    else
    {
        int arr[SEM_NUM] = {1,0};
        for( int i = 0; i < SEM_NUM; i++ )
        {
            union semun a;
            a.val = arr[i];
            if ( semctl(semid,i,SETVAL,a) == -1 )//全新创建成功,就初始化
            {
                printf("semctl err\n");
            }
        }
    }
}
void sem_p(int index)
{
    if ( index < 0 || index >= SEM_NUM )
    {
        return;
    }
    struct sembuf buf;
    buf.sem_num = index;
    buf.sem_op = -1;//p
    buf.sem_flg = SEM_UNDO;
    if ( semop(semid,&buf,1) == -1 )
    {
        printf("sem p err\n");
    }
}
void sem_v(int index)
{
    if ( index < 0 || index >= SEM_NUM )
    {
        return;
    }
    struct sembuf buf;
    buf.sem_num = index;
    buf.sem_op = 1;//v
    buf.sem_flg = SEM_UNDO;
    if ( semop(semid,&buf,1) == -1 )
    {
        printf("sem v err\n");
    }
}
void sem_destroy()
{
    if ( semctl(semid,0,IPC_RMID) == -1 )
    {
        printf("semctl del err\n");
    }
}

3.a.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/shm.h>
#include "sem.h"
int main()
{
    int  shmid = shmget((key_t)1234,256,0600|IPC_CREAT);//创建/获取共享内存
    if ( shmid == -1 )
    {
        printf("shmget err\n");
        exit(0);
    }

    char* s = (char*)shmat(shmid,NULL,0);
    if ( s == (char*)-1 )
    {
        printf("shmat err\n");
        exit(0);
    }

    sem_init();//2  1,0
    while( 1 )
    {
        printf("input\n");
        char buff[128] = {0};
        fgets(buff,128,stdin);
        sem_p(0);
        strcpy(s,buff);
        sem_v(1);
        if ( strncmp(buff,"end",3) == 0 )
        {
            break;
        }
    }

    shmdt(s);
    exit(0);
}

4.b.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/shm.h>
#include "sem.h"
int main()
{
    int  shmid = shmget((key_t)1234,256,0600|IPC_CREAT);//创建/获取共享内存
    if ( shmid == -1 )
    {
        printf("shmget err\n");
        exit(0);
    }

    char* s = (char*)shmat(shmid,NULL,0);
    if ( s == (char*)-1 )
    {
        printf("shmat err\n");
        exit(0);
    }

    sem_init();//2  1,0
    while( 1 )
    {
        printf("input\n");
        char buff[128] = {0};
        fgets(buff,128,stdin);
        sem_p(0);
        strcpy(s,buff);
        sem_v(1);
        if ( strncmp(buff,"end",3) == 0 )
        {
            break;
        }
    }

    shmdt(s);
    exit(0);
}

 

 只运行b.c,会阻塞

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux--信号量共享内存 的相关文章

  • Scrapy FakeUserAgentError:获取浏览器时发生错误

    我使用 Scrapy FakeUserAgent 并在我的 Linux 服务器上不断收到此错误 Traceback most recent call last File usr local lib64 python2 7 site pack
  • 操作系统什么时候清除进程的内存

    进程在某些操作系统上成功或异常终止 操作系统何时决定擦除分配给该进程的内存 数据 代码等 在退出时或当它想为新进程分配内存时 这个清除内存分配过程在所有操作系统 winXP Win7 linux Mac 上都相同吗 据我了解 页表具有该进程
  • gethostbyname() 或 getnameinfo() 如何在后台工作?

    How gethostbyname or getnameinfo 在后台工作 include
  • 如何让 clangd 转向 c++20

    当没有其他信息时 如何让 clangd 回退到 c 20 例如 在第一次构建之前 cmake 可以生成一个 这是在带有最新 LLVM 的 Arch Linux 上 这是通过 Emacs LSP 运行的 但这应该没有什么区别 你可以加 Com
  • gentoo crontab:为什么这个简单的 crontab 不起作用?

    我使用 GENTOO 发行版 crontab e 35 12 root php5 home www cron php 当我手动运行时 php5 php5 home www cron php 这有效 它向我发送了一封电子邮件 然后我检查日期
  • 停止服务时单元陷入故障状态(状态=143)[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这是我的问题 我有 CentOS 和 java 进程在上面运行 Java进程是通过启动 停止脚本来操作的 它也创建了 java 实例的 p
  • Linux 中热插拔设备时检测设备是否存在

    我正在运行 SPIcode http lxr free electrons com source drivers spi spi omap2 mcspi c在熊猫板上 我想知道其中的哪个功能code http lxr free electr
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • 适用于 KDE 和 Gnome 的 Gui [重复]

    这个问题在这里已经有答案了 我想为一个现在是 CLI 的应用程序编写一个 gui 它需要在 KDE 和 Gnome DE 中 看起来不错 充分利用用户的外观设置 如果我选择 Qt 或 GTK 我能够做到这一点吗 它们与两个 DE 集成良好吗
  • Composer 安装要求

    我正在尝试将 Composer 安装到 Laravel 项目中 当我做的时候sudo composer install在项目目录中它显示了两个错误 Problem 1 Installation request for simplesoftw
  • Linux 桌面快捷方式和安装图标

    我需要添加什么到我的 spec文件来创建桌面快捷方式并在安装过程中为快捷方式分配一个图标 rpm 如果需要脚本 一个示例将非常有帮助 您在 Linux 下使用 desktop 文件作为图标 图标放置的位置取决于您使用的发行版和桌面环境 由于
  • 设置 Apache POI 的路径

    我想创建 Excel 文件并使用 java 程序在该文件中写入数据 That is here http www techbrainwave com p 554我在 java 文件所在的位置提取了 Apache POI 并将该路径包含在路径变
  • 归档文件系统或格式

    我正在寻找一种文件类型来存储已退役系统的档案 目前 我们主要使用 tar gz 但从 200GB tar gz 存档中查找并提取几个文件是很麻烦的 因为 tar gz 不支持任何类型的随机访问读取规定 在你明白之前 使用 FUSE 安装 t
  • 在 /dev/input/eventX 中写入事件需要哪些命令?

    我正在开发一个android需要将触摸事件发送到 dev input eventX 的应用程序 我知道C执行此类操作的代码结构如下 struct input event struct timeval time unsigned short
  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7
  • 如何修复“iptables:没有该名称的链/目标/匹配”?

    我在我的 Linux 嵌入式系统上构建并安装了 iptables 如果我列出所有规则 则一切正常 iptables list Chain INPUT policy ACCEPT target prot opt source destinat
  • 何时使用 pthread 条件变量?

    线程问题 看来 只有在其他线程调用 pthread cond notify 之前调用 pthread cond wait 时 条件变量才起作用 如果在等待之前发生通知 那么等待将被卡住 我的问题是 什么时候应该使用条件变量 调度程序可以抢占
  • 为什么我收到“无法进行二进制日志记录”的信息。在我的 MySQL 服务器上?

    当我今天启动 MySQL 服务器并尝试使用以下命令进行一些更改时用于 MySQL 的 Toad http www quest com toad for mysql 我收到此消息 MySQL 数据库错误 无法进行二进制日志记录 消息 交易级别
  • 无法加载 JavaHL 库。- linux/eclipse

    在尝试安装 Subversion 插件时 当 Eclipse 启动时出现此错误 Failed to load JavaHL Library These are the errors that were encountered no libs

随机推荐

  • Doris编译

    使用Doris 官方不提供编译好的jar包 需要自己编译 最方便的方式是通过Docker编译 避免了安装各种环境的繁琐 一 准备服务器 用虚拟机 云服务器都可以编译 不过编译所需要的内存以16G为佳 如果你的机器没有这么多内存 速度会比较慢
  • fatal: unable to access ‘https://github.com/xxx‘: Failed to connect to github.com

    执行这两行命令 端口号改成自己代理服务器的端口 我的是7890 git config global https proxy 127 0 0 1 7890 git config global http proxy 127 0 0 1 7890
  • Bash中各种括号的使用

    Bash中有各种括号 包括单小括号 双小括号 单中括号 双中括号 单大括号 而且它们之间很容易混淆 所以很有必要总结一下它们的用法 1 的用法 单个小括号用来创建一个子shell 例如 pwd home xfeng cd tmp pwd t
  • VMware虚拟网络编辑器配置

    一 NAT模式网络设置 把下面的ip 子网掩码 网关记住 切换到network scripts 目录下 cd etc sysconfig network scripts 修改ifcfg ens33 这个文件 下图圈2的IPADDR设置一个在
  • 洛谷 P1046 陶陶摘苹果

    该问题涉及数组的输入和输出问题 以及数据的换行输入问题 较为简单 题目描述 陶陶家的院子里有一棵苹果树 每到秋天树上就会结出 1010 个苹果 苹果成熟的时候 陶陶就会跑去摘苹果 陶陶有个 3030 厘米高的板凳 当她不能直接用手摘到苹果的
  • sqlilabs—less8

    文章目录 Sqlilabs less8 1 判断注入点 2 爆字段 3 判断数据库 1 判断数据库名长度 2 判断数据库名称 4 判断表 1 有几个表 2 分别判断表长度 3 分别判断表名称 5 判断列 1 判断表中有几个字段 有几列 2
  • Mysql数据库delete操作没报错,却删除不了数据

    1 在操作页面执行删除操作 但没有删除成功 删除过程无报错 以下为删除操作的控制台日志 2 在数据库执行删除操作 表数据 执行删除语句删除staffId为3的数据 结果却没有删除成功 3 原因 staffId为3的数据的flag为Null
  • ImageMagick批量压缩图片

    2019独角兽企业重金招聘Python工程师标准 gt gt gt bin sh for img in find image name jpg do newimg basename img convert quality 75 img ok
  • dolphinscheduler配置之 master.properties/worker.properties及常见问题学习

    master properties master execute thread num master exec threads 50 master execute task number in parallel master exec ta
  • c#读取csv到数组_如何读取CSV文件并将值存储到C#中的数组中?

    CSV文件是逗号分隔的文件 用于以有组织的方式存储数据 它通常以表格形式存储数据 大多数企业组织将其数据存储在CSV文件中 CSV文件是逗号分隔的文件 用于以有组织的方式存储数据 它通常以表格形式存储数据 大多数企业组织将其数据存储在CSV
  • The server time zone value ‘Öйú±ê׼ʱ¼ä‘ is unrecognized or represents more than one time zone

    The server time zone value is unrecognized or represents more than one time zone You must configure either the server or
  • ThreadPoolTaskScheduler轻量级多线程定时任务框架

    ThreadPoolTaskScheduler轻量级多线程定时任务框架 前言 一 ThreadPoolTaskScheduler是什么 二 上干货 1 ThreadPoolTaskScheduler常用的api介绍 2 springboot
  • 华为OD机试 - Linux发行版的数量(Java)

    题目描述 Linux操作系统有多个发行版 distrowatch com提供了各个发行版的资料 这些发行版互相存在关联 例如Ubuntu基于Debian开发 而Mint又基于Ubuntu开发 那么我们认为Mint同Debian也存在关联 发
  • 深度研究:回归模型评价指标R2_score

    回归模型的性能的评价指标主要有 RMSE 平方根误差 MAE 平均绝对误差 MSE 平均平方误差 R2 score 但是当量纲不同时 RMSE MAE MSE难以衡量模型效果好坏 这就需要用到R2 score 实际使用时 会遇到许多问题 今
  • (附源码)springboot考研规划系统 毕业设计 541230

    摘 要 21世纪的今天 随着社会的不断发展与进步 人们对于信息科学化的认识 已由低层次向高层次发展 由原来的感性认识向理性认识提高 管理工作的重要性已逐渐被人们所认识 科学化的管理 使信息存储达到准确 快速 完善 并能提高工作管理效率 促进
  • 懂的都懂,那些好用的“WEB安全”网站

    加密解密 解码编码 MD5 https www cmd5 com 凯撒 https www qqxiuzi cn bianma kaisamima php 摩斯密码 https www jb51 net tools morse htm ht
  • pytorch:数据增广批量化(Batch Augmentation)

    数据增强通常是随机批量生产的 一般使用组合形式 即同时随机裁剪 翻转 旋转等 import torchvision transforms as transforms from PIL import Image import matplotl
  • java中int[] arr和int arr[]有什么区别

    答 是一样的 跟在变量名后面或者跟在类型后面都可以 int arr 这么写不对的 推荐 int arr 写法
  • nodejs第一个程序

    第一个nodejs程序 1 首先创建一个js文件 命名index js 可随意 然后在文件里面输入 console log Hello World 2 使用 Git Bash Here 打开index js文件 输入指令 node inde
  • Linux--信号量共享内存

    1 基础知识 1 共享内存是最快的IPC形式 一旦这样的内存映射到共享它的进程的地址空间 这些进程间的数据传递不再涉及内核 即进程不再通过执行进入内核的系统调用来传递彼此的数据 2 共享内存的生命周期随内核 3 注意 共享内存未提供任何保护