msg 消息队列 | sem信号量 | shm共享内存 | |
创建或者打开 | msgget | semget | shmg |
控制 | msgctl | semctl | shmc |
IPC操作 | msgsnd 发送 | semop | shma |
msgrcv 接收 | shmd |
消息队列的消息:
如果读走了,就没了,如果去读完了再(阻塞)
共享内存的内容一直存在,可以一直读,IPC中最快的一种方式
system V IPC 原理
都是在内核中,搞一个缓冲区,提供了一个操作他们的API 函数
命令: ipcs 查看内核中的 IPC
ipcs -q ipcs -s ipcs -m
流程:
1. 先向 内核申请 一个 IPC key (钥匙 ,许可证): ftok
key_t ftok(const char *pathname, int proj_id);
2. 创建/打开 IPC: msg sem shm
3. 读写操作: 消息队列: msgsnd msgrcv
共享内存: shmat shmdt
信号量: semop
消息队列: 在内核 是 ”一个 带头节点的链表”
int msgget(key_t key, int msgflg);
int msgflg: IPC_CREAT|0644(创建), IPC_EXCL(如果已经存 在就返回错误)
返回值: 成功 返回指向消息队列的 msgid 描述符(int)
失败: -1
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);
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
msgflg: 0 阻塞
IPC_NOWAIT: 非阻塞
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[100]; /* message data */
};
int main()
{
key_t key = ftok("/home/china",'A');
int msqid = msgget(key, IPC_CREAT|0644);
if(msqid < 0)
{
perror("msgget");
return -1;
}
struct msgbuf msg1;
msg1.mtype = 1; //消息的类型
printf("你要发送的消息1:\n");
fgets(msg1.mtext,sizeof(msg1.mtext),stdin);
msgsnd(msqid, &msg1, strlen(msg1.mtext), 0);
msg1.mtype = 2; //消息的类型
printf("你要发送的消息2:\n");
bzero(msg1.mtext,sizeof(msg1.mtext));
fgets(msg1.mtext,sizeof(msg1.mtext),stdin);
msgsnd(msqid, &msg1, strlen(msg1.mtext), 0);
}
共享内存:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
int shmflg: IPC_CREAT|0644(创建), IPC_EXCL(如果已经存 在就返回错误)
返回值: 成功 返回指向消息队列的 shmid 描述符(int)
失败: -1
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
void *shmaddr: 如果填 NULL, 有系统找一个合适的地方映射
int shmflg: 映射的方式
1) SHM_RDONLY 只读
2) 0 可读可写
返回值: 指向 共享内存的 指针
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
cmd: IPC_RMID 删除shmid指向的共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
int main()
{
key_t key = ftok("/home/china",'S');
int shmid = shmget(key, 100, IPC_CREAT|0644);
if(shmid < 0)
{
perror("shmget");
return -1;
}
char *p = shmat(shmid, NULL, 0);
printf("你要发送的消息1:\n");
fgets(p,100,stdin);
shmdt(p);
}
练习: 通过 A, B 聊天 (通过共享内存,或者 消息队列)