1. 概述:
该demo主要实现linux下进程之间的消息队列通信, 相关接口介绍可以参考<<UNIX环境高级编程>>
2. 场景(半双工):
父进程简单地通过消息队列将数据发送给子进程
3. 测试:
/*
demo_process_IPC_msgget.c
进程编程demo(消息队列)
IPC相关的命令: ipcs ipcrm(释放IPC)
查看进程属性: ulimit -a
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/prctl.h>
#define MSG_ID 1
#define MSG_TYPE 2
#define MAX_BUF 64
/*
消息的数据结构有一定的要求, 一定要是以一个长整型成员变量开始的结构体
*/
struct msg_st
{
long int msg_type; /*消息类型*/
char buf[MAX_BUF];
};
int main(int argc, char **argv){
pid_t pid;
key_t key = MSG_ID;
int msgid = -1;
/*
IPC_CREAT | IPC_EXCL, 如果没有该消息队列, 则创建, 并返回消息队列ID
若已有该消息队列, 则返回-1
*/
msgid = msgget(key, 600 | IPC_CREAT | IPC_EXCL);
if(msgid < 0){
/*printf("msgget:%s\n", strerror(errno));*/
perror("msgget:");
return -1;
}
/*
父 -> 子
*/
pid = fork();
if(pid < 0){
perror("fork:");
if (msgctl(msgid, IPC_RMID, 0) < 0){
perror("msgctl:");
}
return -1;
}else if(pid == 0){
prctl(PR_SET_NAME, "child_process");
printf("child process\n"); /*子进程*/
struct msg_st msg;
int recvlength;
memset(&msg, 0x0, sizeof(struct msg_st));
recvlength = sizeof(struct msg_st) - sizeof(long int);
/*
msgtype : 实现一种简单的接收优先级 (非0用于非先进先出次序读消息)
=0 : 获取队列中的第一个消息
>0 : 获取具有相同消息类型的第一个信息
<0 : 获取类型等于或小于msgtype的绝对值的第一个消息
msgflg : 控制当队列中没有相应类型的消息可以接收时将发生的事情
0 表示阻塞方式, IPC_NOWAIT 表示非阻塞方式
*/
if (msgrcv(msgid, &msg, recvlength, 0, 0) < 0){
perror("msgrcv:");
}
printf("child process msgrcv\t msg_type = %ld\t buf = %s\n", msg.msg_type, msg.buf);
}else{
/*
进程重命名
*/
prctl(PR_SET_NAME, "parant_process");
printf("parant process\n"); /*父进程*/
struct msg_st msg;
int sendlength;
char buf[MAX_BUF] = "demo_process_IPC_msgget";
memset(&msg, 0x0, sizeof(struct msg_st));
msg.msg_type = MSG_TYPE; /*重点关注*/
memcpy(msg.buf, buf, strlen(buf));
sendlength = sizeof(struct msg_st) - sizeof(long int);
/*
msgflg : 控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情
0 表示阻塞方式, IPC_NOWAIT 表示非阻塞方式
*/
if (msgsnd(msgid, &msg, sendlength, 0) < 0){
perror("msgsnd:");
}
printf("parant process msgsnd\t msg_type = %ld\t buf = %s\n", msg.msg_type, msg.buf);
wait(NULL);
/*
从系统内核中移走消息队列
*/
if (msgctl(msgid, IPC_RMID, 0) < 0){
perror("msgctl:");
}
}
return 0;
}
#Makefile
CC := gcc
INCLUDE = -I /home/demo/include/
all:
$(CC) demo_process_IPC_msgget.c $(INCLUDE) -o demo_process_IPC_msgget -Wall -Werror
clean:
rm demo_process_IPC_msgget