本文主要是介绍38、IO进程线程/共享内存、信号灯集实现进程间同步通信20240226,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、创建共享内存、和信号灯集实现两个进程间同步通信(进程1先发送,进程2后接收,待2接收完成后,1才能继续发送(用信号灯集实现同步机制,有顺序的先后执行))。
代码:
1信号灯集封装函数头文件:sem.h
#ifndef _SEM_H__
#define _SEM_H__//创建或打开信号灯集:参数为要申请的信号灯集包含的灯的个数,返回信号灯集id
int open_sem(int semcount);//进行申请资源操作:参数为要申请的信号灯集id,以及要申请灯的编号
int P(int semid,int semno);//释放资源操作:参数为要释放的信号灯集id,以及要释放灯的编号
int V(int semid,int semno);//删除信号灯集:参数为要删除的信号灯集id
int del_sem(int semid);#endif
2信号灯集创建、初始化、申请、释放、删除操作
#include<myhead.h>
union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
};int init_semno(int semid,int semno)
{union semun buf;printf("请输入要给编号为%d的灯设置的值:",semno);scanf("%d",&buf.val);getchar();//调用控制函数完成初始化if(semctl(semid,semno,SETVAL,buf)==-1){perror("semctl error");return -1;}return 0;
}
//创建或打开信号灯集:参数为要申请的信号灯集包含的灯的个数,返回信号灯集id
int open_sem(int semcount)
{key_t key=-1;if((key=ftok("/",'s'))==-1){perror("ftok error");return -1;}int semid=-1;//根据key值创建信号灯集if((semid=semget(key,semcount,IPC_CREAT|IPC_EXCL|0664))==-1){if(errno==EEXIST)//如果文件已经存在则直接打开返回semid{semid=semget(key,semcount,IPC_CREAT|0664);return semid;}perror("semget error");return -1;}for(int i=0;i<semcount;i++)//首次打开需要初始化信号灯集{init_semno(semid,i);//对编号为i的灯进行初始化}return semid;
}//进行申请资源操作:参数为要申请的信号灯集id,以及要申请灯的编号
int P(int semid,int semno)
{struct sembuf buf;buf.sem_num=semno;buf.sem_op=-1;buf.sem_flg=1;if(semop(semid,&buf,1)==-1){perror("semop error");return -1;}return 0;
}//释放资源操作:参数为要释放的信号灯集id,以及要释放灯的编号
int V(int semid,int semno)
{ struct sembuf buf;buf.sem_num=semno;buf.sem_op=1;buf.sem_flg=1;if(semop(semid,&buf,1)==-1){perror("semop error");return -1;}return 0;
}//删除信号灯集:参数为要删除的信号灯集id
int del_sem(int semid)
{if(semctl(semid,0,IPC_RMID)==-1){perror("delete error");return -1;}
}
3负责发送信息的进程(使用共享内存)
#include<myhead.h>
#include"sem.h"
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{int semid=open_sem(2);//创建信号灯集key_t key=-1;//创建key值if((key=ftok("/",'m'))==-1){perror("ftok error");return -1;}int shmid=-1;//根据key创建共享内存返回共享内存idif((shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664))==-1){perror("shmget error");return -1;}char *addr=shmat(shmid,NULL,0);//根据shmid将共享内存映射到用户空间if(addr==(void*)-1){perror("shmat error");return -1;}//使用共享内存写入操作while(1){//申请0号灯资源P(semid,0);printf("请输入>>>");fgets(addr,PAGE_SIZE,stdin);addr[strlen(addr)-1]=0;printf("发送成功 \n");//释放1号灯资源V(semid,1);if(strcmp(addr,"quit")==0)break;}//取消映射if(shmdt(addr)==-1){perror("shmdt error");return -1;}//删除共享内存if(shmctl(shmid,IPC_RMID,NULL)==-1){perror("shmctl error");return -1;}return 0;
}
4负责接收信息的进程
#include<myhead.h>
#include"sem.h"
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{//创建信号灯集int semid=open_sem(2);key_t key=-1;//创建key值if((key=ftok("/",'m'))==-1){perror("ftok error");return -1;}int shmid=-1;//根据key创建共享内存返回共享内存idif((shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664))==-1){perror("shmget error");return -1;}char *addr=shmat(shmid,NULL,0);//根据shmid将共享内存映射到用户空间if(addr==(void*)-1){perror("shmat error");return -1;}//使用共享内存读取操作while(1){//申请1号灯资源P(semid,1);printf("收到数据%s\n",addr);if(strcmp(addr,"quit")==0)break;V(semid,0);//释放0号灯资源}//取消映射if(shmdt(addr)==-1){perror("shmdt error");return -1;}//删除信号灯集del_sem(semid);return 0;
}
运行:
思维导图:
这篇关于38、IO进程线程/共享内存、信号灯集实现进程间同步通信20240226的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!