一、共享内存
共享内存是通信效率最高的进程间通信方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;
}