调用原型
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 over
sem_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 over
sem_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 end
pthread_join(s1,NULL);
pthread_join(s2,NULL);
pthread_join(r,NULL);
//delete message queue
msgctl(msgid,IPC_RMID,0);
//delete sem
return 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