进程间通信——共享内存、消息队列、信号灯集

一、共享内存

共享内存是通信效率最高的进程间通信方3式——内存映射(将内核空间地址映射到用户空间,访问该映射空间即相当于访问内核空间)

二、消息队列

就是一些消息的列表。比FIFO具有更大的优势,可以选择性的接受某些消息。

指令 ipcs 查看系统的IPC对象

三、主要函数

       #include <sys/shm.h>
       #include <sys/types.h>
       #include <sys/ipc.h>
/*获取key值*/
       key_t ftok(const char *pathname, int proj_id);
/*创建共享内存*/
       int shmget(key_t key, size_t size, int shmflg);
shmget()返回与参数键的值关联的System V共享内存段的标识符。如果key的值为IPC_PRIVATE或key的值不是IPC_PRIVATE,不存在与key对应的共享内存段,并且在shmflg中指定了IPC_create,则会创建一个新的共享内存段,其大小等于size的值,取整为PAGE_size的倍数。
如果shmflg同时指定IPC_CREAT和IPC_EXCL,并且密钥的共享内存段已经存在,则shmget()将失败,errno设置为EEXIST。(这类似于组合O|u CREAT | O|u EXCL对open(2)的效果。)
/*内存映射*/
       void *shmat(int shmid, const void *shmaddr, int shmflg);
*  If  shmaddr  is NULL, the system chooses a suitable (unused) address at which to attach the segment.
shmflg: SHM_EXEC SHM_RDONLY SHM_REMAP
/*取消映射*/
       int shmdt(const void *shmaddr);
/*关闭共享内存*/
      int shmctl(int shmid, int cmd, struct shmid_ds *buf);
cmd: IPC_RMID
buf: NULL
/*创建消息队列*/
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>

       int msgget(key_t key, int msgflg);
If  msgflg  specifies both IPC_CREAT and IPC_EXCL and a message queue already exists for key, then msgget() fails  with errno  set  to  EEXIST.  (This is analogous to the effect of the combination O_CREAT | O_EXCL for open(2).)
/*发送与接受消息*/
       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);
msqid是msgget返回值
           struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };
msgsz为struct msgbuf中mtext的大小,即正文大小。通过mtype达到有选择性的接受数据
msgflg常用选项:IPC_NOWAIT MSG_COPY MSG_EXCEPT
msgtyp:选择接受的消息类型,即结构体中的第一个元素
/*关闭消息队列*/
      int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:IPC_RMID —— 此时第三个参数会被忽略,填NULL即可

四、实例 

 共享内存与信号灯集

/*########################################################################
# File Name: shm_IPC.c
# Author: tanyaduckal
# mail: 2295375354@qq.com
# Created Time: 2022年01月05日 星期三 10时41分47秒
########################################################################*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define CORVAL 1
#define NORVAL 0
#define ERRVAL -1
#define _STR(x) _VAL(x)
#define _VAL(x) #x
#define handle_error(LOG) do { perror(LOG); exit(EXIT_FAILURE); } while(0)
#define qDbug() do { puts(_STR(__LINE__)); } while(0)

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/sem.h>
#define __pathname "."
#define __proj_id 'a'
#define __shm_size 512
#define __mode 0777
#define __addr_size 64

typedef union semun{
	int val;
}SEM;

/*
typedef struct sembuf{
	unsigned short sem_num;
	short sem_op;
	short sem_flg;
}SEMBUF;
*/

int main(int argc,char **argv){
/******获取key值*******/
	key_t key;
	if(ERRVAL == (key = ftok(__pathname, __proj_id)))
		handle_error("ftok");
/******创建信号灯集*********/
	int semid;
	if(ERRVAL == (semid = semget(key, 2, IPC_CREAT | __mode)))
		handle_error("semget");
/******初始化信号灯集*********/
	struct sembuf buf;
	SEM _semun0, _semun1;
	_semun0.val = 1;
	_semun1.val = 0;
	semctl(semid, 0, SETVAL, _semun0);
	semctl(semid, 1, SETVAL, _semun1);
#if 0
	printf("semun0 = %d, semun1 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
#endif
/******创建共享内存*******/
	int shmid;
	if(ERRVAL == (shmid = shmget(key, __shm_size, __mode | IPC_CREAT)))
		handle_error("shmget");
	char *addr;
/******内存映射*******/
	if((void *)ERRVAL == (addr = shmat(shmid, NULL, 0)))
		handle_error("shmat");
#if 1
/******功能代码*******/
	int i = 1;
	do{
		/******p操作sem0********/
		buf.sem_num = 0;
		buf.sem_op = -1;
		buf.sem_flg = 0;
		semop(semid, &buf, 1);
//		printf("semun0 = %d, semun1 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));

		fgets(addr, __addr_size, stdin);
		if(0 == strncmp(addr, "exit", 4))
			i = 0;

		/******v操作sem1********/
		buf.sem_num = 1;
		buf.sem_op = 1;
		buf.sem_flg = 0;
		semop(semid, &buf, 1);
//		printf("semun0 = %d, semun1 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
	}while(i);
#endif
/******关闭信号灯集****/
	if(ERRVAL == semctl(semid, 0, IPC_RMID))
		handle_error("semctl");
/******取消映射*******/
	if(ERRVAL == shmdt(addr))
		handle_error("shmdt");
/******关闭共享内存*******/
	if(ERRVAL == shmctl(shmid, IPC_RMID, NULL))
		handle_error("shmctl");
	return 0;
}
/*########################################################################
# File Name: shm_IPC.c
# Author: tanyaduckal
# mail: 2295375354@qq.com
# Created Time: 2022年01月05日 星期三 10时41分47秒
########################################################################*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define CORVAL 1
#define NORVAL 0
#define ERRVAL -1
#define _STR(x) _VAL(x)
#define _VAL(x) #x
#define handle_error(LOG) do { perror(LOG); exit(EXIT_FAILURE); } while(0)
#define qDbug() do { puts(_STR(__LINE__)); } while(0)

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/sem.h>
#define __pathname "."
#define __proj_id 'a'
#define __shm_size 512
#define __mode 0777
#define __addr_size 64

typedef union semun{
	int val;
}SEM;

int main(int argc, char **argv){
	key_t key;
	if(ERRVAL == (key = ftok(__pathname, __proj_id)))
		handle_error("ftok");
	int semid;
	if(ERRVAL == (semid = semget(key, 2, IPC_CREAT | __mode)))
		handle_error("semget");
	struct sembuf buf;
	SEM _semun;
#if 1
	_semun.val = 1;
	semctl(semid, 0, SETVAL, _semun);
	_semun.val = 0;
	semctl(semid, 1, SETVAL, _semun);
#endif
//	printf("semun0 = %d, semun1 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
	int shmid;
	if(ERRVAL == (shmid = shmget(key, __shm_size, __mode | IPC_CREAT)))
		handle_error("shmget");
	char *addr;
	if((void *)ERRVAL == (addr = shmat(shmid, NULL, 0)))
		handle_error("shmat");
	/******功能代码*******/
	while(1){
		/***p操作sem1****/
		buf.sem_num = 1;
		buf.sem_op = -1;
		buf.sem_flg = 0;
		semop(semid, &buf, 1);
//		printf("semun0 = %d, semun1 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));

		if(0 == strncmp(addr, "exit", 4))
			break;
		printf("%s", addr);

		/***v操作sem0****/
		buf.sem_num = 0;
		buf.sem_op = 1;
		buf.sem_flg = 0;
		semop(semid, &buf, 1);
//		printf("semun0 = %d, semun1 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
	}

	if(ERRVAL == shmdt(addr))
		handle_error("shmdt");
	/******关闭信号灯集******/
	if(ERRVAL == semctl(semid, 0, IPC_RMID))
		handle_error("semctl");
#if 0
	if(ERRVAL == shmctl(shmid, IPC_RMID, NULL))
		handle_error("shmctl");
#endif
	return 0;
}

消息队列

/*########################################################################
# File Name: msg_IPC.c
# Author: tanyaduckal
# mail: 2295375354@qq.com
# Created Time: 2022年01月05日 星期三 13时34分59秒
########################################################################*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define CORVAL 1
#define NORVAL 0
#define ERRVAL -1
#define _STR(x) _VAL(x)
#define _VAL(x) #x
#define handle_error(LOG) do { perror(LOG); exit(EXIT_FAILURE); } while(0)
#define qDbug() do { puts(_STR(__LINE__)); } while(0)

#include<sys/types.h>
#include<sys/ipc.h>
#define __pathname "."
#define __proj_id 'a'
#include<sys/msg.h>
#define __mode 0777
#define __data_size 1024
#define __mtype typeA
#define typeA 200
#include<unistd.h>

typedef struct msgbuf{
	long mtype;
	char mtext[__data_size];
}MSG;

int main(int argc,char **argv){
	key_t key;
	if(ERRVAL == (key = ftok(__pathname, __proj_id))) handle_error("ftok");
	int msqid;
	if(ERRVAL == (msqid = msgget(key, __mode | IPC_CREAT )))
		handle_error("msqid");
#if 1
	MSG msgp;
	msgp.mtype = __mtype;
	printf("please input mtext\n>");
	fgets((msgp).mtext, __data_size, stdin);

	if(ERRVAL == msgsnd(msqid, (const void *)&msgp, sizeof(msgp)-sizeof(long), IPC_NOWAIT)) handle_error("msgsnd");

	sleep(5);
#endif
	if(ERRVAL == msgctl(msqid, IPC_RMID, NULL)) handle_error("msgctl");
	return 0;
}
/*########################################################################
# File Name: msg_IPC.c
# Author: tanyaduckal
# mail: 2295375354@qq.com
# Created Time: 2022年01月05日 星期三 13时34分59秒
########################################################################*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define CORVAL 1
#define NORVAL 0
#define ERRVAL -1
#define _STR(x) _VAL(x)
#define _VAL(x) #x
#define handle_error(LOG) do { perror(LOG); exit(EXIT_FAILURE); } while(0)
#define qDbug() do { puts(_STR(__LINE__)); } while(0)

#include<sys/types.h>
#include<sys/ipc.h>
#define __pathname "."
#define __proj_id 'a'
#include<sys/msg.h>
#define __mode 0777
#define __data_size 1024
#define __mtype typeA
#define typeA 200

typedef struct msgbuf{
	long mtype;
	char mtext[__data_size];
}MSG;

int main(int argc,char **argv){
	key_t key;
	if(ERRVAL == (key = ftok(__pathname, __proj_id))) handle_error("ftok");
	int msqid;
	if(ERRVAL == (msqid = msgget(key, __mode | IPC_CREAT )))
		handle_error("msqid");
#if 0
	MSG msgp;
	msgp.mtype = __mtype;
	printf("please input mtext\n>");
	fgets((msgp).mtext, __data_size, stdin);

	if(ERRVAL == msgsnd(msqid, (const void *)&msgp, sizeof(msgp)-sizeof(long), IPC_NOWAIT)) handle_error("msgsnd");

#endif

#if 1
	MSG msgp;
	//msgp.mtype = __mtype;

	if((ssize_t)ERRVAL == msgrcv(msqid, (void *)&msgp, sizeof(msgp)-sizeof(long), __mtype, IPC_NOWAIT)) handle_error("msgrcv");

	fputs(msgp.mtext, stdout);
#endif

	if(ERRVAL == msgctl(msqid, IPC_RMID, NULL)) handle_error("msgctl");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值