Linux 下的 msg.h 头文件详解 (msg.h linux)

在 Linux 系统中,msg.h 头文件是消息队列的头文件,主要包含了建立、关闭、发送和接收消息的相关函数的声明。消息队列是多个进程之间进行异步通信的一种方式,常用于进程间通信(IPC)。

本文将对 msg.h 头文件进行详细讲解,包括消息队列的概念、头文件的结构和函数使用方法等。

一、消息队列的概念

消息队列是一种进程间通信的方式,它是一段共享内存,进程可以通过它来传递消息。多个进程可以同时往同一个消息队列中发送消息和从中读取消息,并且每个消息都有一个类型标识。

消息队列有以下几个特点:

1. 消息队列是按照先进先出的规则进行消息的处理。

2. 消息队列中的消息的大小可以自定义,但更大值受系统的限制。

3. 每个消息都有一个类型标识,可以根据类型来选择需要处理的消息。

4. 消息队列适合于进程间的数据量较小,但操作频繁的场景。

5. 消息队列是一种异步通信的方式,不需要等待对方的响应。

二、头文件结构

msg.h 头文件主要包含了以下几个结构体和宏定义:

1. struct msgbuf

该结构体用于保存消息队列中的消息,结构体的定义如下:

“`

struct msgbuf {

long mtype; // 消息类型标识

char mtext[1]; // 消息内容

};

“`

其中,mtype 为消息类型标识,是一个大于 0 的长整型数值,用于区分不同类型的消息。mtext 为消息内容,是一个字符数组,可以保存任意长度的消息。

在使用消息队列时,需要根据实际情况定义结构体的长度,例如:

“`

struct msgbuf {

long mtype; // 消息类型标识

char mtext[1024]; // 消息内容

};

“`

2. struct msqid_ds

该结构体用于保存消息队列的属性,结构体的定义如下:

“`

struct msqid_ds {

struct ipc_perm msg_perm; // 消息队列的权限信息

time_t msg_stime; // 最后一次写入消息队列的时间

time_t msg_rtime; // 最后一次读取消息队列的时间

time_t msg_ctime; // 消息队列的创建时间

unsigned long msg_cbytes; // 消息队列中当前的字节数

unsigned long msg_qnum; // 消息队列中当前的消息数

unsigned long msg_qbytes; // 消息队列中允许的更大字节数

pid_t msg_lspid; // 最后写入消息队列的进程 ID

pid_t msg_lrpid; // 最后读取消息队列的进程 ID

};

“`

其中,msg_perm 是消息队列的权限信息,包括拥有者 ID、群组 ID 和权限标志等信息。msg_stime、msg_rtime 和 msg_ctime 分别表示最后一次写入、读取和创建消息队列的时间。msg_cbytes 表示消息队列中当前的字节数,msg_qnum 表示消息队列中当前的消息数,而 msg_qbytes 则表示消息队列中允许的更大字节数。msg_lspid 和 msg_lrpid 分别表示最后写入和读取消息队列数据的进程 ID。

3. IPC_PRIVATE

IPC_PRIVATE 是一个宏定义,用于表示创建一个新的消息队列,其定义如下:

“`

#define IPC_PRIVATE ((__kernel_key_t)0)

“`

当使用 IPC_PRIVATE 作为 key 值来创建消息队列时,系统将会为其随机生成一个键值,并将该键值作为消息队列的标识符,是一个唯一的值。这种方式创建的消息队列只能在父子进程之间进行通信。

4. IPC_CREAT

IPC_CREAT 是一个宏定义,用于表示创建一个新的消息队列或获取一个已有的消息队列,其定义如下:

“`

#define IPC_CREAT 001000 // 创建新的队列或获取已有队列

#define IPC_EXCL 002023 // 与IPC_CREAT一同使用,用于避免消息队列编号冲突

“`

当使用 IPC_CREAT 和一个正整数 key 配合使用,系统会在内核的消息队列中通过该 key 值查找是否已经存在一个具有相同 key 值的消息队列。如果不存在,则创建一个新的消息队列,并返回该消息队列的标识符;如果已经存在,则返回该消息队列的标识符。当同时使用 IPC_CREAT 和 IPC_EXCL 标志时,如果已经存在一个具有相同 key 值的消息队列,则创建操作将失败,返回 -1。

三、消息队列相关函数

msg.h 头文件中包含了多个函数,用于创建、添加、获取和删除消息队列。其中,常用函数有:

1. int msgget(key_t key, int msg);

该函数用于创建或获取一个消息队列,其参数 key 用于指定消息队列的键值,msg 用于指定消息队列的访问权限和创建方式。返回消息队列的标识符,出错返回 -1。

2. int msgsnd(int msqid, const void *msgp, size_t msgsz, int msg);

该函数用于向指定消息队列中添加消息,其参数 msqid 为消息队列的标识符,msgp 为消息的指针,msgsz 为消息的长度,msg 为消息的标志。返回成功添加消息的长度,出错返回 -1。

3. ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msg);

该函数用于从指定消息队列中读取消息,其参数 msqid 为消息队列的标识符,msgp 为消息的指针,msgsz 为消息的长度,msgtyp 为消息类型标识,msg 为消息的标志。返回读取到的消息的长度,出错返回 -1。

4. int msgctl(int msqid, int cmd, struct msqid_ds *buf);

该函数用于控制指定消息队列的属性,其参数 msqid 为消息队列的标识符,cmd 为操作命令,buf 为消息队列的属性结构体指针。返回成功为 0,出错返回 -1。

其中,cmd 可以设置为以下值:

– IPC_RMID:删除指定的消息队列;

– IPC_STAT:获取指定的消息队列的属性;

– IPC_SET:设置指定的消息队列的属性。

四、使用示例

下面是一个简单的使用消息队列的示例程序:

“`

#include

#include

#include

#include

#include

#include

#include

struct msgbuf {

long mtype;

char mtext[1024];

};

int mn() {

int msgid;

key_t key;

struct msgbuf buf;

// 创建一个新的消息队列,并获取其标识符

key = ftok(“.”, ‘a’);

msgid = msgget(key, IPC_CREAT | 0666);

if (msgid == -1) {

printf(“msgget error: %s\n”, strerror(errno));

exit(1);

}

// 添加三个消息

buf.mtype = 1;

strcpy(buf.mtext, “message 1”);

if (msgsnd(msgid, &buf, strlen(buf.mtext), 0) == -1) {

printf(“msgsnd error: %s\n”, strerror(errno));

exit(1);

}

buf.mtype = 2;

strcpy(buf.mtext, “message 2”);

if (msgsnd(msgid, &buf, strlen(buf.mtext), 0) == -1) {

printf(“msgsnd error: %s\n”, strerror(errno));

exit(1);

}

buf.mtype = 1;

strcpy(buf.mtext, “message 3”);

if (msgsnd(msgid, &buf, strlen(buf.mtext), 0) == -1) {

printf(“msgsnd error: %s\n”, strerror(errno));

exit(1);

}

// 读取消息队列中的消息

while(1) {

if (msgrcv(msgid, &buf, 1024, 0, IPC_NOWT) != -1) {

printf(“recvd msg: %s\n”, buf.mtext);

} else {

if (errno != ENOMSG) {

printf(“msgrcv error: %s\n”, strerror(errno));

}

break;

}

}

// 删除消息队列

if (msgctl(msgid, IPC_RMID, NULL) == -1) {

printf(“msgctl error: %s\n”, strerror(errno));

exit(1);

}

return 0;

}

“`

该程序使用 ftok 函数生成一个新的键值,并调用 msgget 函数创建一个新的消息队列,然后使用 msgsnd 函数向消息队列中添加三个消息,消息类型分别为 1、2 和 1。接着使用 msgrcv 函数从消息队列中读取所有的消息,并输出到标准输出的终端上。最后使用 msgctl 函数删除该消息队列。

五、

相关问题拓展阅读:

windows与linux 头文件对照

别折腾了,重写吧……

1.linux和windows平台下,能够对应的头文件就是符合C11标准的头文件。其他的头文件不仅和平台有关系握亩搏,还和平台下的编译环境有关,很难画上等号的。

2.C语言符合标准的头文件

#include //设定插入点

#include //字符处理

#include //定义错误码

#include //浮点数处理

#include //文件输入/输出

#include //参数化输入/输出

#include //数据流输入/输出

#include //定义各种数据类型最值常量

#include //定义本地化函数

#include //定义数学函数

#include //定义输入/输出函数

#include //定义杂项函数及内存分配函数

#include //字符串处理

#include //基于数组的输入/输出

#include //定义关于时间的函数

#include //宽字符处理及输入/输出

#include //宽字符分类

3.linux常用头文件如下:

POSIX标准定义的头文件

目录项

文件控制

文件名匹配类型

路径名模式匹配类型

组文件

网络数段祥据库操作

口令文件

正则表达式

TAR归档值

终端I/O

符号常量

文件时间

字符扩展类型

INTERNET定义

套接字本地接口

INTERNET地址族

传输控制协议定义

内存管理声明

Select函数

套接字借口

文件状态

进程时间

基本系统数据类型

UNIX域套接字定义

系统名

进程控制

POSIX定义的XSI扩展头文件

cpio归档值

动态链接

消息显示结构

文件树漫游

代码集转换使用程序

语言信息常量

模式匹配函数定义

货币类型

数据库操作

消息类别

轮询函数

搜索表

字符耐举串操作

系统出错日志记录

用户上下文

用户限制

用户帐户数据库

IPC(命名管道)

消息队列

资源操作

信号量

共享存储

文件系统信息

时间类型

附加的日期和时间定义

矢量I/O操作

POSIX定义的可选头文件

异步I/O

消息队列

线程

执行调度

信号量

实时spawn接口

XSI STREAMS接口

事件跟踪

看看红旗linux,他们出的书具体不太记得了,不过毕竟是中国做得更好的,多看看有帮助。

Linux的一般接口在《Unix环境高级编程》中有详细的描述。

关于socket,请看《Unix网络编程》一书。

如果用型晌图形界面,那么Linux下通常采用的是GDK和Qt两个库,也就是说,如果你在Windows下使散租慧用了包含图形界面的库函数,那么你就必须修改你的所有函数调用的实现,而不仅仅是替换头文件。

要做跨平台的程序,我推荐你使用冲答Qt,它用C++写成,对于图形界面的操作可以直接在Win\Mac\*nix等各种平台下使用。

祝你好运!

应该差不多的

Ros中msg创建.h的问题

在安装好ROS后,接着学习如何创建节点和节点之间的通信方式,以一个简瞎唯穗单的主题发布节点和主题订阅节点说明。节点是连接ROS网络等可执行文件,是实现某山信些功能的软件包,也是一个主要计算执磨卜行的进程。

wiki教程上说,在xml和CMakeLists文件里添加相关依链差赖以后,编译,.msg文件会被转化成.h文件。

这激码就是为什么只看源码找不到部分

头文件

的原因。你看看是不是xml里没加build_depends,棚铅皮或者CMakeLists里面没加find_packge.

自己测试结果如下,当你按照wiki教程吵闷写好cmakelist.txt之后,枝仿之一次catkin_make会生成Num.h。之后就可以猛碰纤 #include 了。

关于msg.h linux的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux 下的 msg.h 头文件详解 (msg.h linux)