Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式
Linux系统是一种支持多任务并发执行的操作系统,它可以同时运行多个进程,从而提高系统的利用率和效率。但是,如果这些进程之间需要进行数据交换和协作,就需要使用一些进程间通信(IPC)的方式,例如信号、共享内存、信号量等。其中,System V 消息队列是一种比较经典而可靠的IPC方式,它可以让两个或多个进程通过一个队列来进行消息传递,无需关心消息的内容和格式。本文将介绍Linux系统中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中文网其他相关文章!

学习Linux并不难。1.Linux是一个开源操作系统,基于Unix,广泛应用于服务器、嵌入式系统和个人电脑。2.理解文件系统和权限管理是关键,文件系统是层次化的,权限包括读、写和执行。3.包管理系统如apt和dnf使得软件管理方便。4.进程管理通过ps和top命令实现。5.从基本命令如mkdir、cd、touch和nano开始学习,再尝试高级用法如shell脚本和文本处理。6.常见错误如权限问题可以通过sudo和chmod解决。7.性能优化建议包括使用htop监控资源、清理不必要文件和使用sy

Linux管理员的平均年薪在美国为75,000至95,000美元,欧洲为40,000至60,000欧元。提升薪资可以通过:1.持续学习新技术,如云计算和容器技术;2.积累项目经验并建立Portfolio;3.建立职业网络,拓展人脉。

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

互联网运行不依赖单一操作系统,但Linux在其中扮演重要角色。Linux广泛应用于服务器和网络设备,因其稳定性、安全性和可扩展性受欢迎。

Linux操作系统的核心是其命令行界面,通过命令行可以执行各种操作。1.文件和目录操作使用ls、cd、mkdir、rm等命令管理文件和目录。2.用户和权限管理通过useradd、passwd、chmod等命令确保系统安全和资源分配。3.进程管理使用ps、kill等命令监控和控制系统进程。4.网络操作包括ping、ifconfig、ssh等命令配置和管理网络连接。5.系统监控和维护通过top、df、du等命令了解系统运行状态和资源使用情况。

介绍 Linux是一个强大的操作系统,由于其灵活性和效率,开发人员,系统管理员和电源用户都喜欢。但是,经常使用长而复杂的命令可能是乏味的

Linux适用于服务器、开发环境和嵌入式系统。1.作为服务器操作系统,Linux稳定高效,常用于部署高并发应用。2.作为开发环境,Linux提供高效的命令行工具和包管理系统,提升开发效率。3.在嵌入式系统中,Linux轻量且可定制,适合资源有限的环境。

简介:通过基于Linux的道德黑客攻击数字边界 在我们越来越相互联系的世界中,网络安全至关重要。 道德黑客入侵和渗透测试对于主动识别和减轻脆弱性至关重要


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6
视觉化网页开发工具

WebStorm Mac版
好用的JavaScript开发工具

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

记事本++7.3.1
好用且免费的代码编辑器