在 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 函数删除该消息队列。
五、
相关问题拓展阅读:
别折腾了,重写吧……
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后,接着学习如何创建节点和节点之间的通信方式,以一个简瞎唯穗单的主题发布节点和主题订阅节点说明。节点是连接ROS网络等可执行文件,是实现某山信些功能的软件包,也是一个主要计算执磨卜行的进程。
wiki教程上说,在xml和CMakeLists文件里添加相关依链差赖以后,编译,.msg文件会被转化成.h文件。
这激码就是为什么只看源码找不到部分
头文件
的原因。你看看是不是xml里没加build_depends,棚铅皮或者CMakeLists里面没加find_packge.
自己测试结果如下,当你按照wiki教程吵闷写好cmakelist.txt之后,枝仿之一次catkin_make会生成Num.h。之后就可以猛碰纤 #include 了。
关于msg.h linux的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
香港服务器选创新互联,2H2G首月10元开通。
创新互联(www.cdcxhl.com)互联网服务提供商,拥有超过10年的服务器租用、服务器托管、云服务器、虚拟主机、网站系统开发经验。专业提供云主机、虚拟主机、域名注册、VPS主机、云服务器、香港云服务器、免备案服务器等。
文章名称:Linux下的msg.h头文件详解(msg.hlinux)
网站链接:http://www.shufengxianlan.com/qtweb/news7/414557.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联