Linux消息队列与信号量

2023-05-16

Linux消息队列与信号量

一、消息队列

概念:消息队列是由内核负责维护管理的链式数据队列,不是根据先后顺序出队,而是根据消息类型进行收发数据

int msgget(key_t key, int msgflg);

功能:创建\获取消息队列
        key:IPC键值
        msgflg:
            IPC_CREAT  消息队列已存在则获取,否则创建
            IPC_EXCL   消息队列已存在则返回错误
注意:如果创建需要提供权限
返回值:IPC标识符,失败-1
    
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    功能:向消息队列发送消息包
    msqid:IPC标识符
    msgp:要发送的消息包的首地址
        struct msgbuf {
           long mtype;      //  消息类型
           char mtext[n];   //  数据,不一定是字符串,可以是任意数据类型
       };
    msgsz:数据的字节数,不包含消息类型,例如上面数据变成结构体时,传参为:sizeofstruct- sizeoflong)
    msgflg:
        阻塞发送一般给0
        IPC_NOWAIT 当消息队列满,不等待立即返回

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
    功能:从消息队列中接收对应消息包的数据
    msqid:IPC标识符
    msgp:存储消息包的内存首地址
    msgsz:存储数据的内存字节数(尽量大些)
    msgtyp:消息类型(按照类型获取,不按照顺序)
        >0 读取消息类型=msgtyp的消息
        =0 读取消息队列中第一条消息
        <0 读取消息类型小于abs(msgtyp)的消息,如果有多个则读值最小的
    msgflg
        IPC_NOWAIT 消息队列都不符合时不阻塞,立即返回
        MSG_EXCEPT 如果msgtyp>0,则读取第一条不等于msgtyp的消息
        MSG_NOERROR 如果不包含此标志,如果实际发送过来的数据字节数>接收的字节数,则返回失败,如果包含此标志,那么就只读取接收的字节数,一定会成功
    返回值:成功读取到数据的字节数

int msgctl(int msqid,int cmd,struct msqid_ds *buf);
功能:获取\修改消息队列的属性、删除队列
msqid:IPC标识符
cmd:
    IPC_STAT   获取消息队列属性 buf输出型参数
    IPC_SET    设置消息队列属性 buf输入型参数
    IPC_RMID   删除消息队列     NULL
buf

编程模型:

进程A进程B
创建消息队列获取消息队列
发送消息获取消息
获取消息发送消息
删除消息队列

二、信号量

概念:由内核管理的一个"全局变量",用于记录共享资源的数量,限制进程对共享资源的访问使用

信号量是一种数据操作锁,本身是不具备数据交互功能,而是通过控制其他的通信资源从而配合实现进程间通信
1、如果信号量的值大于0,说明可以使用资源,使用时需要信号量-1,然后再使用
2、如果信号量的值等于0,说明没有资源可使用,此时进程进入休眠,直到信号量的值大于0,进程会被唤醒,执行步骤1
3、当资源使用完毕,把信号量的值+1,正在休眠的进程就会被唤醒

int semget(key_t key, int nsems, int semflg);
功能:创建\获取信号量
key:IPC键值
nsems:信号量的数量 一般写1
semflg:IPC_CREAT  信号量已存在则获取,否则创建
        IPC_EXCL   信号量已存在则返回错误
        注意:如果创建需要提供权限
返回值:IPC标识符 失败-1

int semctl(int semid, int semnum, int cmd, ...);
功能:删除、控制信号量
semid:IPC标识符
semnum:要操作的第几个信号量,从0开始,下标
cmd:
    IPC_STAT   获取信号量属性 buf输出型参数
    IPC_SET    设置信号量属性 buf输入型参数
    IPC_RMID   删除信号量     NULL
    SETVAL     设置某个信号量的值
    SETALL     设置所有信号量的值
    GETVAL      获取某个信号量的值
    GETALL      获取所有信号量的值
    GETNCNT     获取等待拿资源的进程数量

int semop(int semid,struct sembuf *sops,size_t nsops);
功能:对信号量进行加减操作
semid:IPC标识符
sembuf{
    unsigned short sem_num;  // 信号量的下标
    short          sem_op;   //
            1 信号量+1
            -1 信号量-1 如果不能减,则默认阻塞
    short          sem_flg;  //
            IPC_NOWAIT 不阻塞
            SEM_UNDO 如果进程终止没有手动还资源,系统会自动还
nsops:结构体个数,第二个参数可以是结构体数组                
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux消息队列与信号量 的相关文章

  • 如何通过替换为空页映射来取消映射 mmap 文件

    Linux 用户空间有没有办法用空页面 映射自 dev null 或者可能是一个空页面 重复映射到从文件映射的页面的顶部 对于上下文 我想找到这个 JDK bug 的修复 https bugs openjdk java net browse
  • 使用 grep 查找包含所有搜索字符串的行

    我有一个文件 其中包含很多与此类似的行 id 2796 some model Profile message type MODEL SAVE fields account 14 address null modification times
  • GLIBCXX_3.4.26 未找到在 BeagleBone 上运行交叉编译的程序

    我有以下程序 include
  • 仅打印“docker-container ls -la”输出中的“Names”列

    发出时docker container ls la命令 输出如下所示 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a67f0c2b1769 busybox tail f dev
  • 如何在 shell 脚本中并行运行多个实例以提高时间效率[重复]

    这个问题在这里已经有答案了 我正在使用 shell 脚本 它读取 16000 行的输入文件 运行该脚本需要8个多小时 我需要减少它 所以我将其划分为 8 个实例并读取数据 其中我使用 for 循环迭代 8 个文件 并在其中使用 while
  • 为什么内核需要虚拟寻址?

    在Linux中 每个进程都有其虚拟地址空间 例如 32位系统为4GB 其中3GB为进程保留 1GB为内核保留 这种虚拟寻址机制有助于隔离每个进程的地址空间 对于流程来说这是可以理解的 因为有很多流程 但既然我们只有 1 个内核 那么为什么我
  • 无法从 jenkins 作为后台进程运行 nohup 命令

    更新 根据下面的讨论 我编辑了我的答案以获得更准确的描述 我正在尝试从詹金斯运行 nohup 命令 完整的命令是 nohup java jar home jar server process 0 35 jar prod gt gt var
  • 域套接字“sendto”遇到“errno 111,连接被拒绝”

    我正在使用域套接字从另一个进程获取值 就像 A 从 B 获取值一样 它可以运行几个月 但最近 A 向 B 发送消息时偶尔会失败 出现 errno 111 连接被拒绝 我检查了B域套接字绑定文件 它是存在的 我也在另一台机器上做了一些测试 效
  • 如何在数组中存储包含双引号的命令参数?

    我有一个 Bash 脚本 它生成 存储和修改数组中的值 这些值稍后用作命令的参数 对于 MCVE 我想到了任意命令bash c echo 0 0 echo 1 1 这解释了我的问题 我将用两个参数调用我的命令 option1 without
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 如何将目录及其子目录中的所有 PDF 文件复制到一个位置?

    如何全部复制PDF文件从目录及其子目录到单个目录 实际上还有更多的文件 并且深度有些任意 假设四个目录的最大深度是公平的 我想这些文件需要重命名 如果a pdf例如 位于多个目录中 因为我会adding https ebooks stack
  • Linux 内核标识符中前导和尾随下划线的含义是什么?

    我不断遇到一些小约定 比如 KERNEL Are the 在这种情况下 是内核开发人员使用的命名约定 还是以这种方式命名宏的语法特定原因 整个代码中有很多这样的例子 例如 某些函数和变量以 甚至 这有什么具体原因吗 它似乎被广泛使用 我只需
  • os.Mkdir 和 os.MkdirAll 权限

    我正在尝试在程序开始时创建一个日志文件 我需要检查是否 log如果不创建目录 则目录存在 然后继续创建日志文件 好吧 我尝试使用os Mkdir 也os MkdirAll 但无论我在第二个参数中输入什么值 我都会得到一个没有权限的锁定文件夹
  • 如何在apache 2.4.6上安装apxs模块

    我刚刚用过apt get update我的 apache 已更新为2 4 6 我想安装 apxs 来编译模块 但收到此错误 The following packages have unmet dependencies apache2 pre
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • iptables通过注释删除特定规则

    我需要删除一些具有相同评论的规则 例如 我有带有 comment test it 的规则 所以我可以像这样获得它们的列表 sudo iptables t nat L grep test it 但是我怎样才能删除所有带有注释 测试它 的 PR
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少
  • SSE:跨页边界的未对齐加载和存储

    我在页面边界旁边执行未对齐加载或存储之前读过某处 例如使用 mm loadu si128 mm storeu si128内在函数 代码应首先检查整个向量 在本例中为 16 个字节 是否属于同一页 如果不属于同一页 则切换到非向量指令 我知道
  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我

随机推荐