1.进程通信
- 管道:包括无名管道(pipe)和命名管道(named
pipe),无名管道可用于具有父进程和子进程之间的通信。命名管道除具有管道所具有的所有功能外,它还允许无亲缘关系进程间的通信。 - 消息队列:进程可以向队列中添加消息,其他进程可以读取队列中的消息
- 信号(signal)
- 共享内存:多个进程可以共同访问一块内存
- 信号量(semaphore):用于进程之间对共享资源进行加锁
- 套接字:可用于不同计算机之间的进程间通信
2.共享内存
多个进程共享一块内存,共享内存并未提供锁机制。如果需要对共享内存的读写加锁,可以使用信号。
2.2 查看共享内存的指令
ipcs -m 可以查看共享内存
ipcrm -m 共享内存编号 手工删除共享内存
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mutex>
#include <sys/types.h>
#include <unistd.h>
// 共享内存大小
#define BUFFSIZE 1024
//写共享内存
int main(int argc, char *argv[]) {
// 共享内存的标识
int shmid;
// 共享内存的key
key_t key = 0x5005;
char* shmaddr = nullptr;
char* msg = nullptr;
//创建共享内存
if ((shmid = shmget(key, BUFFSIZE, IPC_CREAT | 0640)) < 0) {
printf("shmget error!\n");
}
printf("Create shared-memory success, with shmid: %d\n", shmid);
//将共享内存连接到当前进程的地址空间,由shmaddr指针指向它
if ((shmaddr = (char*)shmat(shmid, NULL, 0)) < 0) {
printf("shmat error!\n");
}
//拷贝数据到共享内存,需要用互斥锁
printf("写入前:%s\n", shmaddr);
sprintf(shmaddr, "本程序 的进程号是:%d", getpid());
printf("写入后:%s\n", shmaddr);
//把共享内存从当前进程中分离
shmdt(shmaddr);
//删除共享内存
if(shmctl(shmid, IPC_RMID, 0) == -1)
{printf("shmctl(ox5005) failed\n"); return -1;}
return 0;
}
3. 信号量
信号量是一种同步机制,用于协调并发访问共享资源的进程或线程之间的互斥和同步。信号量通常用于临界区控制、进程同步和进程间通信。
ipcs -s 查看信号量
ipcrm sem 信号量标识 删除信号量
#include "CSEM.h"
bool CSEM::init(key_t key)
{
if((sem_id = semget(key, 1, 0640)) == -1)//0640权限
{
//如果信号量不存在,创建它
if(errno == 2)
{
if((sem_id = semget(key, 1, 0640 | IPC_CREAT)) == -1){printf("init 1 semget()"); return false;}
//信号灯创建成功后,还需要把它初始化为可用状态
union semun sem_union;
sem_union.val = 1;
if(semctl(sem_id, 0, SETVAL, sem_union) < 0){printf("init semctl"); return false;}
}
else {perror("init 2 segment()"); return false;}
}
return true;
}
bool CSEM::wait()
{
struct sembuf sem_b;
sem_b.sem_num = 0;//信号量集的个数,单个信号量设置为0
sem_b.sem_op = -1;//信号量在本次操作中需要改变的数据,-1等待操作,1发送操作
sem_b.sem_flg = SEM_UNDO;//把此标志设置为SEM_UNDO,OS将跟踪这个信号量,
//如果当前进程退出时没有释放信号量,操作系统释放信号量,避免资源被锁死
if(semop(sem_id, &sem_b, 1) == -1){perror("wait semop()"); return false;}
return true;
}
bool CSEM::post()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1){perror("post semop()"); return false;}
return true;
}
bool CSEM::destory()
{
if(semctl(sem_id, 0, IPC_RMID) == -1){perror("destroy semctl()");return false;}
return true;
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/sem.h>
class CSEM
{
private:
union semun//用于信号灯操作的共同体
{
int val;
struct semid_ds *buf;
unsigned short *arry;
};
int sem_id;//信号灯描述
public:
bool init(key_t key); //如果信号灯已存在,获取信号灯;不存在,则创建信号灯并初始化
bool wait(); //等待信号灯挂出
bool post(); //挂出信号灯
bool destory(); //销毁信号灯
};
#include "CSEM.h"
int main(int argc, char* argv[])
{
CSEM sem;
//初始化信号灯
if(sem.init(0x5000) == false){printf("sem init failed!\n");return -1;}
printf("init ok\n");
//等待信号 成功后将持有锁
if(sem.wait() == false) {printf("wait failed!\n");return -1;}
printf("sem ok!\n");
sleep(20);
//挂出信号灯,释放锁
if(sem.post() == false) {printf("sem.post failed!\n");return -1;}
printf("sem post ok!\n");
}