调用原型
POSIX信号量–无名信号量
POSIX信号量是Pthread线程库提供的一种同步机制,包括无名信号量和有名信号量两种机制。无名信号量,常用于多线程间的同步,也可用于相关进程间的同步(需置于相关进程间的共享内存区中)。有名信号量通过IPC名字进行进程间的同步,特点是把信号量保存在文件中,可用于线程、相关进程和不相关进程间的同步。
#include <semaphore.h>
int sem_init(sem_t *sem,int pshared,unsigned int value)
创建无名信号量,sem(信号量名称),pshared一般为0(多线程间的同步),value(信号量的初始值)
int sem_wait(sem_t *sem)
阻塞申请资源
int sem_post(sem_t *sem)
释放资源
IPC消息队列通信机制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
消息缓冲区struct msgbuf
需重新定义
struct msgbuf{long mtype;char mytext[1024];
}
int msgget(key_t key,int msgflag)
创建消息队列
int msgnd(int msqid,struct msgbuf* msgp,size_t msgsz,int msgflg)
发送消息
ssize_t msgrcv(int msqid,struct msgbuf* msgp,size_t msgsz,long msgtyp,int msgflg)
接收消息
int msgctl(int msqid,int cmd,struct msqid_ds* buf)
删除消息队列
Pthread线程库
#include <pthread.h>
pthread_create()
创建线程
pthread_join()
阻塞等待进程
pthread_exit()
线程结束
具体实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <unistd.h>sem_t mutex_que;
sem_t over1,over2;
sem_t s_server,r_server;
sem_t msgid_mutex;int msgid=-1;struct msgbuf
{long mtype;char mytext[1024];
};void* sender1(){int flag1=1;struct msgbuf buf;int error;while(flag1){memset(&buf,0,sizeof(buf));sem_wait(&s_server);sem_wait(&msgid_mutex);if(msgid==-1){msgid=msgget(0,IPC_CREAT);if(msgid==-1){printf("message queue error --sender1\n");sem_post(&msgid_mutex);exit(1);}}sem_post(&msgid_mutex);sem_wait(&mutex_que);printf("sender1> ");scanf("%s",buf.mytext);buf.mtype=1;if(!strncmp(buf.mytext,"exit",4)){flag1=0;strcpy(buf.mytext,"end1");}else{strcat(buf.mytext," --sender1");}error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);if(error==-1){printf("sender1 message send error\n");sem_post(&mutex_que);exit(1);}sem_post(&mutex_que);sem_post(&r_server);}//wait for signal oversem_wait(&s_server);sem_wait(&over1);sem_wait(&mutex_que);error=msgrcv(msgid,&buf,sizeof(buf.mytext),2,IPC_NOWAIT);if(!strncmp(buf.mytext,"over1",5)){printf("sender1: ");printf("%s --receiver\n",buf.mytext);sem_post(&mutex_que);sem_post(&s_server);pthread_exit(NULL);}
}void* sender2(){int flag2=1;struct msgbuf buf;int error;while(flag2){memset(&buf,0,sizeof(buf));sem_wait(&s_server);sem_wait(&msgid_mutex);if(msgid==-1){sem_post(&s_server);sem_post(&msgid_mutex);continue;}sem_post(&msgid_mutex);sem_wait(&mutex_que);printf("sender2> ");scanf("%s",buf.mytext);buf.mtype=1;if(!strncmp(buf.mytext,"exit",4)){flag2=0;strcpy(buf.mytext,"end2");}else{strcat(buf.mytext," --sender2");}error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);if(error==-1){printf("sender2 message send error\n");sem_post(&mutex_que);exit(1);}sem_post(&mutex_que);sem_post(&r_server);}//wait for signal oversem_post(&s_server);sem_wait(&over2);sem_wait(&mutex_que);error=msgrcv(msgid,&buf,sizeof(buf.mytext),2,IPC_NOWAIT);if(!strncmp(buf.mytext,"over2",5)){printf("sender2: ");printf("%s --receiver\n",buf.mytext);sem_post(&mutex_que);sem_post(&s_server);pthread_exit(NULL);}
}void* receiver(){int flag1=1;int flag2=1;struct msgbuf buf;int error;while(flag1!=0||flag2!=0){memset(&buf,0,sizeof(buf));sem_wait(&r_server);sem_wait(&mutex_que);error=msgrcv(msgid,&buf,sizeof(buf.mytext),1,IPC_NOWAIT);if(flag1&&!strncmp(buf.mytext,"end1",5)){memset(&buf,0,sizeof(buf));strcpy(buf.mytext,"over1");buf.mtype=2;error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);if(error==-1){printf("receiver send message error\n");sem_post(&mutex_que);exit(1);}sem_post(&over1);sem_post(&mutex_que);sem_post(&s_server);flag1=0;}else{if(flag2&&!strncmp(buf.mytext,"end2",5)){memset(&buf,0,sizeof(buf));strcpy(buf.mytext,"over2");buf.mtype=2;error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);if(error==-1){printf("receiver send message error\n");sem_post(&mutex_que);exit(1);}sem_post(&over2);flag2=0;sem_post(&mutex_que);sem_post(&s_server);}else{if(strlen(buf.mytext)!=0){printf("receive: %s \n",buf.mytext);sem_post(&mutex_que);sem_post(&s_server);}}}}printf("all end\n");
}int main(){sem_init(&msgid_mutex,0,1);sem_init(&mutex_que,0,1);sem_init(&over1,0,0);sem_init(&over2,0,0);sem_init(&s_server,0,1);sem_init(&r_server,0,0);pthread_t s1,s2,r;int error;error=pthread_create(&s1,NULL,sender1,NULL);if(error!=0){printf("sender1 create error\n");exit(1);}error=pthread_create(&s2,NULL,sender2,NULL);if(error!=0){printf("sender2 create error\n");exit(1);}error=pthread_create(&r,NULL,receiver,NULL);if(error!=0){printf("receiver create error\n");exit(1);}//block wait threads endpthread_join(s1,NULL);pthread_join(s2,NULL);pthread_join(r,NULL);//delete message queuemsgctl(msgid,IPC_RMID,0);//delete semreturn 0;
}
实现效果
参考
1.参考实现
https://blog.csdn.net/CPromise/article/details/127929525
2.API手册
https://www.bookstack.cn/read/linuxapi/SUMMARY.md
3.sem信号量
https://blog.csdn.net/qq_19923217/article/details/82902442