IPC:Inter Process Communicate
中间 进程 通信
根据操作系统(os)不同会有不同的两个版本:ANSI版本 和 POSIX版本
共享内存:shm share memory
多个进程都可以访问os之上的一块内存段
消息队列:msg message queue
在主机上指定一个或多个队列
不同进程可以发送消息到队列中,或者从队列中获取消息(按照对应类型拿)
旗语(信号量):sem semaphore
多个进程不可能同时访问一块区域
用一个整数 进程都能对它做加减操作
加 随便加
减 最小减到0(阻塞)
以上三种都要使用到key
key的本质是一个int类型的整数,保证IPC的唯一性
key都是通过fd创建
用来查看当前主机的IPC的命令:ipcs
共享内存编程模型:
1.创建key ftok
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
proj_id 非零整数 8个bit位 1-255
2.创建共享内存 shmget
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
3.挂载共享内存 shmat
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
4.使用
5.卸载共享内存 shmdt
6.删除共享内存 shmctl
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmA shmB
1.创建key ftok 1.创建key ftok
2.创建共享内存 shmget 2.获取共享内存
3.挂载共享内存 shmat 3.挂载
4.使用 4.使用
5.卸载共享内存 shmdt 5.卸载
6.删除共享内存 shmctl
信号(因为需要所以这里简单讲点):
信号是个整数,os提供了64个信号(主要是前32个)
特殊行为用对应的信号来表示
终端强制结束一个进程 SIGINT 2
杀进程 SIGKILL 9
...
本身信号的处理是固定的,不同信号有不同的处理方式
我们可以使用signal函数,自己注册信号的处理
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
消息队列编程模型:
1.创建key
2.创建消息队列
msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
3.收发消息
msgrcv 接收
msgsnd 发送
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
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);
注意:接收消息会按照类型接收(msgtyp)
4.删除消息队列 msgctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
旗语(信号量)编程模型:
1.创建key ftok
2.创建信号量 semget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
3.初始化信号量 semctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
4.使用信号量 semop
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, size_t nsops);
5.删除信号量 semctl
相关示例:
#include <stdio.h>
#include <unistd.h> //linux操作系统标准头文件
#include <string.h> //memcpy
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> //umask
#include <time.h>
#include <sys/time.h>
#include <dirent.h> //遍历目录
#include <fcntl.h> //文件映射虚拟内存
#include <sys/mman.h>
#include <wait.h>
#include <signal.h> //SIGCHLD
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <poll.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <bits/pthreadtypes.h>
#include <aio.h>
#include <netdb.h>
#include <netinet/ip_icmp.h>
// 信号
void hand(int s)
{
printf("收到信号:%d\n", s);
}
void _signal()
{
signal(2, hand);
int n = 0;
while (1)
{
printf("%d\n", n++);
sleep(1);
}
}
// shmctl删除共享内存
void _shmctl()
{
// 1.创建key ftok
key_t key = ftok("./", 'm');
if (-1 == key)
{
printf("创建key失败%m\n");
return -1;
}
printf("创建key成功\n");
// 2.创建共享内存 shmget
int shmid = shmget(key, 4096, IPC_CREAT | 0666);
if (-1 == shmid)
{
printf("创建共享内存失败%m\n");
return -1;
}
printf("创建共享内存成功\n");
#if 0
//3.删除共享内存
int r = shmctl(shmid,IPC_RMID,NULL);
if (-1 == r)
{
printf("删除共享内存失败%m\n");
return -1;
}
printf("删除共享内存成功\n");
#else
// 获取共享内存状态
struct shmid_ds ds = {0};
int r = shmctl(shmid, IPC_STAT, &ds);
if (-1 == r)
{
printf("获取共享内存失败%m\n");
return -1;
}
printf("获取共享内存成功\n");
printf("挂载数:%d\n", ds.shm_nattch);
printf("创建进程id:%d\n", ds.shm_cpid);
printf("大小:%d\n", ds.shm_segsz);
#endif
}