两种锁可以使用上面的四种互斥量进行自动加锁和解锁
区别:
std::condition_variable, 要搭配着mutex来使用,主要的函数为wait和notify函数。
wait函数:
- wait:有两个重载的函数void wait( std::unique_lockstd::mutex& lock )和void wait( std::unique_lockstd::mutex& lock, Predicate stop_waiting ),第二个比第一个加了pred条件,为true的时候才接触阻塞。
- wait_for:增加了一个超时时间
- wait_util: 直到某个时间点
notify函数
- notify_one: 唤醒一个阻塞进程
- notify_all: 唤醒所有阻塞进程
无名管道用于有亲缘关系的进程间的通信,因为这样双方才能同时拥有管道的信息。工作方式为半双工。读端和写端固定。
读写的内容存在于内存中。
通过pipe接口创建,返回读端口和写端口:
int pfd[2]={0};//定义无名管道数组,只有两个端口,所以大小为2
int ret=pipe(pfd);//pipe--创建无名管道
write(pfd[1],"hello", 5);
int n = read(pfd[0], buff, 5)
有名管道的创建之后会在文件系统中以管道文件的形式存在;
有名管道可以用于任意两个进程间的通信,没有固定的读端和写端。
int mkfifo(const char *pathname, mode_t mode);
int ret=mkfifo("fifo",0755);//0664赋文件权限
//写端打开
int fd=open("fifo",O_WRONLY)
write(fd,buf,strlen(buf));//写入
//读端打开
int fd=open("fifo",O_RDONLY);//以‘仅读’打开管道
read(fd,buf,64);//读取缓冲区
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
消息队列同样存在缺点:
//用来创建和访问一个消息队列
int msgget(key_t key, int msgflg);
//消息队列的控制函数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
//把一条消息添加到消息队列中
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//从一个消息队列接收消息
size_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
key_t key;
key=ftok("./msgfile",'a');
msgid=msgget(key, IPC_CREAT |IPC_EXCL|0666); //通过文件对应
ret = msgsnd(msgid,&msgbuf, sizeof(msgbuf.data), IPC_NOWAIT);
ret=msgrcv(msgid, &msgbuf, sizeof(msgbuf.data), msgtype, IPC_NOWAIT);
信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
//信号量存在
sem_t *sem_open(const char *name, int oflag);
//信号量不存在
sem_t *sem_open(const char *name, int oflag,
mode_t mode, unsigned int value);
int sem_close(sem_t *sem); //关闭信号量
int sem_unlink(const char *name); //删除信号量文件
sem_wait(sem); // p操作
//v操作+1
sem_post(sem);
由于进程通信的本质是要让两个不同的进程看到同一份资源,我们可以在物理内存上开辟一块空间,这块空间被称为共享内存,然后让这两个进程通过某种方式都能访问到这块内存,这样的话,两个进程之间就可以通信了。
共享内存操作默认不阻塞,如果多个进程同时读写共享内存,可能出现数据混乱,共享内存需要借助其他机制来保证进程间的数据同步,比如:信号量,共享内存内部没有提供这种机制。
int shm_open(const char *name, int oflag, mode_t mode);//成功返回非负的描述符,失败返回-1
int shm_unlink(const char *name)//shm_unlink用于删除一个共享内存区对象,跟其他文件的unlink以及其他POSIX IPC的删除操作一样,对象的析构会到对该对象的所有引用全部关闭才会发生。
shm_fd = shm_open("shm-update", O_CREAT|O_RDWR, 0777);
ftruncate(shm_fd, 1024);
shm_data = mmap(NULL,1024, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, SEEK_SET);
key_t ftok(const char *pathname, int proj_id)
//创建或者打开一个共享内存
int shmget(key_t key, size_t size, int shmflg);// shmflg: IPC_CREATE, IPC_excl
//关联和解除关联函数shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
//
int shmdt(const void *shmaddr);