首页 > 系统相关 >进程间通信 消息队列

进程间通信 消息队列

时间:2023-04-03 17:33:55浏览次数:36  
标签:IPC 队列 msgid 间通信 key 进程 include define

System V IP

  • IPC : Inter-Process Communication (进程间通讯)
  • System V 是早期的unix 系统,曾经被称为 AT & T System ,是 unix 操作系统中比较重要的一个分支,现在Linux 系统一般都支持 System V IPC
  • System V IPC 对象共有三种
    • 消息队列
    • 共享内存
    • 信号量
  • System V IPC 是由内核维护的若千个对象,通过 ipcs 命名查询
  • 每个 IPC 对象都有一个唯一的 ID,可以通过 ftok() 函数生成,fork 函数具体说明如下:
    函数头文件
    #include <sys/types.h>
    #include <sys/ipc.h>
    函数原型
    key_t ftok(const char *pathname, int proj_id);
    函数参数
  • pathname : 文件路径名
  • proj_id : 8 it的id 整数

函数返回值

  • 成功: 返回合成的 key
  • 失败:-1,并设置 errno

注意:

  • key 由文件的 inode 节点号 与 proi id 构成
  • inode 节点号 : 每个存在的文件操作系统都会有唯一的编号,通过 ls -i命令查看

消息队列简介

  • 消息队列就是一个消息的列表,进程可以在消息队列中添加消息和的读取消息
  • 消息队列具有一定的FIFO特性,具有无名管道与有名管道的各自的优势,可以支持任意两个进程的进程间通讯
  • 消息队列是属于 sytem v ipc 的一种由内核维护与管理 可以通过 ipcs -q 查看

创建消息队列

  • 创建消息队列调用 msgget 函数
    函数头文件
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    函数原型
    int msgget(key_t key, int msgflg);
    函数参数
    • key : 由 ftok 函数合成
    • msgflg : 消息队列标志
      • IPC CREAT:创建标志
      • IPC EXCL: 如果消息队列,则报错,errno 设置为 EEXIST
    • 权限控制标志
      函数返回值
    • 成功 : 返回 消息队列 id
    • 失败: 返回-1,并设置 errno

创建一个消息队列,并打印消息队列 ID

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define PATHNAME "."
#define PROID 10

int main(){
        key_t key;
        int msgid;

        key = ftok(PATHNAME,PROID);
        if(key == -1){
                perror("[ERROR] ftok:");
                exit(EXIT_FAILURE);
        }
        msgid = msgget(key,IPC_CREAT | 0666);
        if(msgid == -1){
                perror("[ERROR] msgget():");
                exit(EXIT_FAILURE);
        }
        printf("msg id: %d\n",msgid);
        return 0;


}

通过 ipcs -q 命名查看后:

  • 对于已经创建的消息队列,如果 key 一样,则直接获取这个消息队列ID,对于新创建的消息队列,每次消息队列的ID 不一定相同,即使key一致

示例: 创建两个没有血缘关系的进程,使用 消息队列进行通讯

  • read.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>

#define PATHNAME "."
#define PRO_ID 10

#define MSG_TYPE 100
#define MSG_SZ 64
struct msgbuf {
        long mtype;
        char mtext[MSG_SZ];
};
int main(void){
        int ret,msgid;
        key_t key;
        ssize_t rbytes;
        struct msgbuf buf;

        key = ftok(PATHNAME,PRO_ID);
        if(key == -1){
                perror("[ERROR] ftok()");
                exit(EXIT_FAILURE);
        }
        msgid = msgget(key,IPC_CREAT | 0666);
        if(msgid == -1){
                perror("[ERROR] msgget");
                exit(EXIT_FAILURE);
        }
        fprintf(stdout,"%d\n",msgid);
        rbytes = msgrcv(msgid, (void *)&buf,MSG_SZ,MSG_TYPE,0);
        if(rbytes == -1){
                perror("[ERROR] msgrcv():");
                exit(EXIT_FAILURE);
        }
        fprintf(stdout,"mtype:%ld\n",buf.mtype);
        fprintf(stdout,"mtext:%s\n",buf.mtext);
        ret = msgctl(msgid,IPC_RMID,NULL);
        if(ret == -1){
                perror("msgctl():");
                exit(EXIT_FAILURE);
        }
        return 0;

}
  • write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define PATHNAME "."
#define PRO_ID 10

#define MSG_TYPE 100
#define MSG_SZ 64

struct msgbuf {
        long mtype;
        char mtext[MSG_SZ];
};
int main(void){
        key_t key;
        int msgid,ret;
        struct msgbuf buf;
        key = ftok(PATHNAME,PRO_ID);
        if(key == -1){
                perror("ftok()");
                exit(EXIT_FAILURE);
        }
        msgid = msgget(key,IPC_CREAT | 0644);
        if(ret == -1){
                perror("msgget():");
                exit(EXIT_FAILURE);
        }
        fprintf(stdout,"msgid:%d\n",msgid);
        buf.mtype = MSG_TYPE;
        strcpy(buf.mtext,"Hello msg");
        ret = msgsnd(msgid,(const void *)&buf,strlen(buf.mtext)+1,0);
        if(ret == -1){
                perror("msgsnd():");
                exit(EXIT_FAILURE);
        }
        return 0;

}

标签:IPC,队列,msgid,间通信,key,进程,include,define
From: https://www.cnblogs.com/shubin/p/17283745.html

相关文章

  • rabbitmq消息队列之持久化
    在生产过程中,难免会发生服务器宕机的事情,RabbitMQ也不例外,可能由于某种特殊情况下的异常而导致RabbitMQ宕机从而重启,那么这个时候对于消息队列里的数据,包括交换机、队列以及队列中存在消息恢复就显得尤为重要了。RabbitMQ本身带有持久化机制,包括交换机、队列以及消息的持久化。......
  • 【CSAPP】进程 | 上下文切换 | 用户视角下的并发进程
     ......
  • 详细解析Java异步线程处理队列任务工具类以及实战
    场景待入快速理解小场景描述:【一群人】来到【一个大厅】办理业务,大厅中有【多个窗口】给我们办理业务。每个人都有自己要办事情,处理过程需要消耗时间。大厅根据人群多少,开始窗口梳理。如果把“一群人”理解成一群待处理的n个【任务】,把这群人排成一个长队就形成了一个【任......
  • XmlTextReader正由另一进程使用,因此该进程无法访问此文件
    此处调用报错:publicvoidsetMaxValueByXml(stringJym,stringvalueMax){XmlDocumentxmlDoc=newXmlDocument();xmlDoc.Load(Server.MapPath("XMLData.xml"));XmlNodeListnodeList=xmlDoc.SelectSingleNode("body")......
  • C#额外管理进程
    1、额外打开进程关闭进程(放在程序打开或者关闭时比如aubdioftp服务)publicstaticvoidStartFtpPress(){stringpath=System.Environment.CurrentDirectory;stringfileName=path+"\\FtpAudio.exe";System.Diagnostics......
  • 数据结构 第三章 栈与队列
    之前期末考试,大部分都是二叉树,先根遍历之类的,还有一些辨析题目,一些很零碎的知识点,关于二叉树,这些的栈1.栈的概念首先对于线性表来说,线性表的插入和删除操作可以在任意的位置进行,而栈的插入和删除操作只允许在表的尾端进行。栈中,允许进行插入和删除操作的一端称为栈顶,另一端称......
  • Linux系统下进程回收--waitpid函数
    waitpid函数的作用和wait函数的作用相同,只是有些参数不同。在Linux终端下输入命令:man2waitpid查看waitpid函数的具体描述:SYNOPSIS#include<sys/types.h>#include<sys/wait.h>pid_twaitpid(pid_tpid,int*wstatus,intoptions);......
  • 进程和端口
    进程和端口查看命令Linux中的ps命令是**ProcessStatus**的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,**如果想要动态的显示进程信息,就可以使用top命令**。要对进程进行监测和控制,首先必须要了解当......
  • 进程间通讯
    一、关于进程间通讯linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。每个进程都有自己独立的地址空间,当两个不同进程需要进行交互时,就需要使用进程间通讯进程间通讯分为单个计算机的进程间通讯与局域网的计算机的进程间通讯进程间通讯方式有管道,信......
  • 计算机网络学习总结(进程之间的通信)
    进程之间通信的方式之一是利用socket最近学习了计算机网络的一些知识,下面是我自己的一些简单理解,可能有些错误的地方(狗头保命)首先长报文在发送的时候是以分组的形式发送的,由应用层发送应用层报文到运输层然后运输层对接收到的每个分组加上一个运输层首部,然后发送到网络层网络......