目录
模型" >模型
ftok()" >ftok()
msgget()" >msgget()
msgsnd()" >msgsnd()
msgrcv()" >msgrcv()
msgctl()" >msgctl()
例子" >例子
首页 系统教程 操作系统 Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式

Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式

Feb 12, 2024 pm 03:33 PM
linux linux教程 linux系统 linux命令 外壳脚本 typedef lsp 嵌入式linux linux入门 linux学习

Linux系统是一种支持多任务并发执行的操作系统,它可以同时运行多个进程,从而提高系统的利用率和效率。但是,如果这些进程之间需要进行数据交换和协作,就需要使用一些进程间通信(IPC)的方式,例如信号、共享内存、信号量等。其中,System V 消息队列是一种比较经典而可靠的IPC方式,它可以让两个或多个进程通过一个队列来进行消息传递,无需关心消息的内容和格式。本文将介绍Linux系统中System V 消息队列的方法,包括消息队列的创建、打开、发送、接收、关闭和删除等方面。

Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式

模型

#include 
#include 
#include 
ftok()               //获取key值                               
msgget()             //创建/获取消息队列                        
msgsnd()/msgrcv()    //发消息到消息队列/从消息队列收信息        
msgctl()             //删除消息队列                           
登录后复制

ftok()

//获取key值, key值是System V IPC的标识符,成功返回key,失败返回-1设errno
//同pathname+同 proj_id==>同key_t;
key_t ftok(const char *pathname, int proj_id);
登录后复制

pathname :文件名
proj_id: 1~255的一个数,表示project_id

key_t key=ftok(".",100);    //“.”就是一个存在且可访问的路径, 100是假设的proj_id
    if(-1==key)
        perror("ftok"),exit(-1);
登录后复制

msgget()

//创建/获取消息队列,成功返回shmid,失败返回-1
int msgget(key_t key, int msgflg);  //ATTENTION:用int msqid=msgget()比较好看
登录后复制

msgflg:具体的操作标志

  • IPC_CREAT 若不存在则创建, 需要在msgflg中"|权限信息"; 若存在则打开
  • IPC_EXCL若存在则创建失败
  • 0 获取已经存在的消息队列

消息队列的容量由msg_qbytes控制,在消息队列被创建的过程中,这个大小被初始化为MSGMNB,这个限制可以通过msgctl()修改

int msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664);
if(-1==msqid)
    perror("msgget"),exit(-1);
登录后复制

msgsnd()

//向指定的消息队列发送指定的消息,如果消息队列已经满了,默认的行为是堵塞,直到队列有空间容纳新的消息,成

功返回0,失败返回-1设errno
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
登录后复制

msqid msgget()返回的消息队列的ID
msgp消息的的首地址, 消息的参考数据类型如下

struct msgbuf {
    long mtype;       /* message type, must be > 0 */   //消息的类型
    char mtext[1];    /* message data */                //消息的内容
};
ATTENTION:The  mtext field is an array (or other structure) whose size is
 specified by msgsz, a nonnegative integer value. 
登录后复制

msgsz消息的大小, 该参数用于指定消息内容的大小, 不包括消息的类型。只能sizeof(Msgbuf.mtext),不能sizeof(Msgbuf)
msgflg发送的标志, 默认给0即可

Msg msg1={1,"hello"};//消息的类型是1,内容是hello
int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
if(-1==res)
    perror("msgsnd"),exit(-1);
登录后复制

msgrcv()

//向指定的消息队列取出指定的消息,成功返回实际接受到的byte数,失败返回-1设errno
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
登录后复制

msqid: 消息队列的ID(returned by msgget)
msgp: 存放接收到消息的缓冲区首地址
msgsz: 消息的最大大小, 不包括消息的类型==>只能sizeof(Msgbuf.mtext),不能sizeof(Msgbuf)

  • 如果消息的长度>msgsz且msgflg里有MSG_NOERROR,则消息会被截断,被截断的部分会丢失
  • 如果消息的长度>msgsz且msgflg里没有MSG_NOERROR,那么会出错,报E2BIG。

msgtyp: 消息的类型

  • 0:读取消息队列中的第一个消息
  • >0:读取消息队列中第一个type为msgtype的消息, 除非msg_flg里有MSG_EXCEPT,此时队列中的第一个不是msgtyp的消息会被读取
  • 读取消息队列中type

msgflg: 发送的标志, 默认给0即可

Msg msg1;
int res=msgrcv(msqid,&msg1,sizeof(msg1.buf),1,0);
if(-1==res)
    perror("msgrcv"),exit(-1);
登录后复制

msgctl()

// 消息操作,成功返回0,失败返回-1设errno
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
登录后复制

msqid :消息队列的ID,由msgget()
buf 结构体指针

struct msqid_ds {
    struct ipc_perm msg_perm;       /* Ownership and permissions */
    time_t          msg_stime;      /*Time of last msgsnd(2) */
    time_t          msg_rtime;      /* Time of last msgrcv(2) */
    time_t          msg_ctime;      /* Time of last change */
    unsigned long   __msg_cbytes;   /* Current number of bytes in queue (nonstandard) */
    msgqnum_t       msg_qnum;       /* Current number of messages in queue */
    msglen_t        msg_qbytes;     /* Maximum number of bytes allowed in queue */
    pid_t           msg_lspid;      /* PID of last msgsnd(2) */
    pid_t           msg_lrpid;      /* PID of last msgrcv(2) */
};
struct ipc_perm {
    key_t           __key;      /* Key supplied to msgget(2) */
    uid_t           uid;        /* Effective UID of owner */
    gid_t           gid;        /* Effective GID of owner */
    uid_t           cuid;       /* Effective UID of creator */
    gid_t           cgid;       /* Effective GID of creator */
    unsigned short  mode;       /* Permissions */
    unsigned short  __seq;      /* Sequence number */
};
登录后复制

cmd

  • IPC_STAT从内核相关结构体中拷贝消息队列相关的信息到buf指向的结构体中

  • IPC_SET把buf指向的结构体的内容写入到内核相关的结构体中,同时更显msg_ctimer成员,同时以下成员也会被更新:msg_qbytes, msg_perm.uid, msg_perm.gid, msg_perm.mode。调用队列的进程的effective UID必须匹配队列所有者或创建者的msg_perm.uid或msg_perm.cuid或者该进程拥有特权级别,

  • IPC_RMID立即销毁消息队列,唤醒所有正在等待读取或写入该消息队列进程,调用的进程的UID必须匹配队列所有者或创建者或者该进程拥有足够的特权级别

  • IPC_INFO (Linux-specific)返回整个系统对与消息队列的限制信息到buf指向的结构体中

    //_GNU_SOURCE
    //
    struct msginfo {
        int msgpool;/*Size in kibibytes of buffer pool used to hold message
     data; unused within kernel*/
        int msgmap; /*Maximum number of entries in message map; unused within 
    kernel*/
        int msgmax; /*Maximum number of bytes that can be written in a single
     message*/
        int msgmnb; /*Maximum number of bytes that can be written to queue; 
    used to initialize msg_qbytes  during queue creation*/
        int msgmni; /*Maximum number of message queues*/
        int msgssz; /*Message segment size; unused within kernel*/
        int msgtql; /*Maximum number of messages on all queues in system; unused
     within kernel*/
        unsigned short int  msgseg; /*Maximum number of segments; unused
     within kernel*/
    };
    
    登录后复制
    int res=msgctl(msqid,IPC_RMID,NULL);
    if(-1==res)
    perror("msgctl"),exit(-1);
    
    登录后复制

例子

//Sys V IPC msg
#include
#include
#include
#include
#include
typedef struct{
    long mtype;     //消息的类型
    char buf[20];       //消息的内容
}Msg;
int msqid;          //使用全局变量,这样就可以在fa中使用msqid了
void fa(int signo){
    printf("deleting..\n");
    sleep(3);
    int res=msgctl(msqid,IPC_RMID,NULL);
    if(-1==res)
        perror("msgctl"),exit(-1);
    exit(0);
}
int main(){
    //ftok()
    key_t key=ftok(".",150);
    if(-1==key)
        perror("ftok"),exit(-1);
    printf("key%#x\n",key);
    //msgget()
    msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664);
    if(-1==msqid)
        perror("msgget"),exit(-1);
    printf("msqid%d\n",msqid);
    //msgsnd()
    Msg msg1={1,"hello"};//消息的类型是1,内容是hello
    Msg msg2={2,"world"};
    int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
    if(-1==res)
        perror("msgsnd"),exit(-1);
    res=msgsnd(msqid,&msg1,sizeof(msg1.buf),0);
    if(-1==res)
        perror("msgsnd"),exit(-1);
    //msgctl()
    //Ctrl+C delete msq
    printf("Press CTRL+C to delete msq\n");
    if(SIG_ERR==signal(SIGINT,fa))
        perror("signal"),exit(-1);
    while(1);
    return 0;
}
登录后复制

本文介绍了Linux系统中System V 消息队列的方法,包括消息队列的创建、打开、发送、接收、关闭和删除等方面。通过了解和掌握这些知识,我们可以更好地使用System V 消息队列来实现进程间通信,提高系统的稳定性和效率。当然,Linux系统中System V 消息队列还有很多其他的特性和用法,需要我们不断地学习和研究。希望本文能给你带来一些启发和帮助。

以上是Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

vscode需要什么电脑配置 vscode需要什么电脑配置 Apr 15, 2025 pm 09:48 PM

VS Code 系统要求:操作系统:Windows 10 及以上、macOS 10.12 及以上、Linux 发行版处理器:最低 1.6 GHz,推荐 2.0 GHz 及以上内存:最低 512 MB,推荐 4 GB 及以上存储空间:最低 250 MB,推荐 1 GB 及以上其他要求:稳定网络连接,Xorg/Wayland(Linux)

vscode 无法安装扩展 vscode 无法安装扩展 Apr 15, 2025 pm 07:18 PM

VS Code扩展安装失败的原因可能包括:网络不稳定、权限不足、系统兼容性问题、VS Code版本过旧、杀毒软件或防火墙干扰。通过检查网络连接、权限、日志文件、更新VS Code、禁用安全软件以及重启VS Code或计算机,可以逐步排查和解决问题。

notepad怎么运行java代码 notepad怎么运行java代码 Apr 16, 2025 pm 07:39 PM

虽然 Notepad 无法直接运行 Java 代码,但可以通过借助其他工具实现:使用命令行编译器 (javac) 编译代码,生成字节码文件 (filename.class)。使用 Java 解释器 (java) 解释字节码,执行代码并输出结果。

vscode 可以用于 mac 吗 vscode 可以用于 mac 吗 Apr 15, 2025 pm 07:36 PM

VS Code 可以在 Mac 上使用。它具有强大的扩展功能、Git 集成、终端和调试器,同时还提供了丰富的设置选项。但是,对于特别大型项目或专业性较强的开发,VS Code 可能会有性能或功能限制。

vscode是什么 vscode是干什么用的 vscode是什么 vscode是干什么用的 Apr 15, 2025 pm 06:45 PM

VS Code 全称 Visual Studio Code,是一个由微软开发的免费开源跨平台代码编辑器和开发环境。它支持广泛的编程语言,提供语法高亮、代码自动补全、代码片段和智能提示等功能以提高开发效率。通过丰富的扩展生态系统,用户可以针对特定需求和语言添加扩展程序,例如调试器、代码格式化工具和 Git 集成。VS Code 还包含直观的调试器,有助于快速查找和解决代码中的 bug。

VSCode怎么用 VSCode怎么用 Apr 15, 2025 pm 11:21 PM

Visual Studio Code (VSCode) 是一款跨平台、开源且免费的代码编辑器,由微软开发。它以轻量、可扩展性和对众多编程语言的支持而著称。要安装 VSCode,请访问官方网站下载并运行安装程序。使用 VSCode 时,可以创建新项目、编辑代码、调试代码、导航项目、扩展 VSCode 和管理设置。VSCode 适用于 Windows、macOS 和 Linux,支持多种编程语言,并通过 Marketplace 提供各种扩展。它的优势包括轻量、可扩展性、广泛的语言支持、丰富的功能和版

Linux的主要目的是什么? Linux的主要目的是什么? Apr 16, 2025 am 12:19 AM

Linux的主要用途包括:1.服务器操作系统,2.嵌入式系统,3.桌面操作系统,4.开发和测试环境。Linux在这些领域表现出色,提供了稳定性、安全性和高效的开发工具。

git怎么查看仓库地址 git怎么查看仓库地址 Apr 17, 2025 pm 01:54 PM

要查看 Git 仓库地址,请执行以下步骤:1. 打开命令行并导航到仓库目录;2. 运行 "git remote -v" 命令;3. 查看输出中的仓库名称及其相应的地址。

See all articles