📄 stopwait.c
字号:
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <signal.h>#include <time.h>#include <string.h>#if defined (__GNU_LIBRARY__)&& !defined (_SEM_SEMUN_UNDEFINED)#elseunion semun{ int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf;};#endif#define SHMDATASIZE 1000#define BUFFERSIZE (SHMDATASIZE -sizeof(int))#define byte int8_t#define SEND 0#define START 1#define FRAME 2#define SHARE 3int Semid,length;void delete (void);void sigdelete (int signum);void locksem (int semid,int semnum);void unlocksem (int semid,int semnum);void waitzero(int semid,int semnum);void write (int shmid,int semid,char *buffer);int mysemget (key_t kye,int nsems,int semflg);int mysemctl (int shmid,int semnum,int cmd,union semun arg);int mysemop (int semid,struct sembuf *sops,unsigned nsops);int myshmget (key_t key,int size,int shmflg);void *myshmat (int shmid,const void *shmaddr,int shmflg);int myshmctl (int shmid,int cmd,struct shmid_ds *buf);struct DataFrame //数据帧{ byte PRE; byte NS; int DATA[80]; unsigned int FCS; byte EOT;};struct AckFrame //确认,否定帧{ byte PRE; byte NR; int ACK; unsigned int FCS; byte EOT;};int main (int argc,char *argv[]){ char selection[3],*buffer; union semun sunion;
int semid,shmid,length=10,j,k;
void *shmdata; struct DataFrame SendFrame[21],*send; struct AckFrame ReceiveFrame,*receive; pid_t pid1,pid2;
semid=mysemget(IPC_PRIVATE,4,SHM_R|SHM_W);
Semid=semid;
//atexit(&delete);
//signal(SIGINT,&sigdelete);
sunion.val=1;
mysemctl(semid,SEND,SETVAL,sunion); mysemctl(semid,SHARE,SETVAL,sunion);
sunion.val=0; mysemctl(semid,FRAME,SETVAL,sunion);
mysemctl(semid,START,SETVAL,sunion); shmid=myshmget(IPC_PRIVATE,SHMDATASIZE,IPC_CREAT|SHM_R|SHM_W); shmdata=myshmat(shmid,0,0); *(int *)shmdata=0; buffer=shmdata+sizeof(int); buffer[0]='0'; buffer[1]='1'; //myshmctl(shmid,IPC_RMID,NULL); //printf("请输入要传递的帧数(1~20):\n"); //scanf("%d",&length); srand(time(NULL)); for(j=1;j<=length;j++) { for(k=0;k<80;k++) SendFrame[j].DATA[k]=rand()%2; SendFrame[j].PRE=0x00; SendFrame[j].EOT=0x04; } ReceiveFrame.PRE=0x00; ReceiveFrame.EOT=0x04; ReceiveFrame.ACK=1; receive=shmdata+sizeof(int)+2*sizeof(char); *receive=ReceiveFrame;
pid1=fork(); //*********************************************************************核心代码************************************************************ if(pid1){//父进程,为发送方 int count=0; char *temp; int i,j,f=1; while(count<=length&&f==1){ locksem(semid,SEND); //等待SEND信号 locksem(semid,SHARE); //获得进入共享内存的互斥信号量 temp=shmdata+sizeof(int); receive=shmdata+sizeof(int)+2*sizeof(char); ReceiveFrame=*receive; if( temp[0]=='0' && temp[1]=='1' && ReceiveFrame.ACK==1 )count++;//如果是确认帧则发送下一帧,否则将上一个帧重发 *(int *)shmdata=count; temp[0]=temp[1]='1'; send=shmdata+2*sizeof(char)+sizeof(int); *send=SendFrame[count]; if(count>length){ printf("全部帧发送完毕!\n"); exit(0); } printf("**********************************发送进程**************************************\n"); printf("第%d帧发出,数据为:\n",count); fflush(stdout); for(j=0;j<80;j++){ printf("%d",SendFrame[count].DATA[j]); fflush(stdout); } printf("\n**********************************发送进程**************************************\n\n\n"); unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 unlocksem(semid,START); //通知计时器可以开始计时 unlocksem(semid,FRAME); //通知接受进程有帧到达 pid2=fork(); if(!pid2){ //父进程中的子进程,作为计时器用 locksem(semid,START); //等待计时信号 sleep(3); //计时3秒 locksem(semid,SHARE); //获得进入共享内存的互斥信号量 temp=shmdata+sizeof(int); if((*(int *)shmdata)==count && temp[0]=='1'){ temp[1]='0'; printf("**********************************计时器进程************************************\n"); printf("超时,要求发送进程重新发送!\n"); printf("**********************************计时器进程************************************\n\n\n\n\n"); unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 unlocksem(semid,SEND); }else{ unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 } f=0; //标记位,使定时器进程计完时后自动结束 } } }else{ //子进程,即接受进程 while(1){ char *temp,selection[3]; int cou; locksem(semid,FRAME); //等待有数据帧到达 locksem(semid,SHARE); //获得进入共享内存的互斥信号量 cou=*(int *)shmdata; if(cou>length)break; temp=shmdata+sizeof(int); send=shmdata+sizeof(int)+2*sizeof(char); SendFrame[0]=*send; printf("**********************************接受进程**************************************\n"); printf("第%d帧到达,数据为:\n",cou); fflush(stdout); for(j=0;j<80;j++){ printf("%d",SendFrame[0].DATA[j]); fflush(stdout); } printf("\n接受 1 /拒绝 2 /丢弃 3 ?\n"); //接受用户输入 fflush(stdout); fgets (selection,sizeof (selection),stdin); switch(selection[0]){ case '1': if(temp[1]=='1'){ temp[0]='0'; receive=shmdata+sizeof(int)+2*sizeof(char); ReceiveFrame.ACK=1; //返回确认帧 *receive=ReceiveFrame; unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 unlocksem(semid,SEND); }else{ unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 } break; case '2':if(temp[1]=='1'){ temp[0]='0'; receive=shmdata+sizeof(int)+2*sizeof(char); ReceiveFrame.ACK=0; //返回否认帧 *receive=ReceiveFrame; unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 unlocksem(semid,SEND); }else{ unlocksem(semid,SHARE); //释放进入共享内存的互斥信号量 } break; default:unlocksem(semid,SHARE);break; } printf("**********************************接受进程**************************************\n\n\n\n\n"); } } //*********************************************************************核心代码************************************************************ return 0;}
void delete(void){
printf("\n quit;delete the semaphore %d \n",Semid);
union semun sem;
if(mysemctl(Semid,0,IPC_RMID,sem) == -1) {
printf("Error releasing semaphore. \n");
}
}
void sigdelete(int signum){
exit(0);
}
void locksem(int semid,int semnum){
struct sembuf sb;
sb.sem_num=semnum;
sb.sem_op=-1;
sb.sem_flg=SEM_UNDO;
mysemop(semid,&sb,1);
}
void unlocksem(int semid,int semnum){
struct sembuf sb;
sb.sem_num=semnum;
sb.sem_op=1;
sb.sem_flg=SEM_UNDO;
mysemop(semid,&sb,1);
}
void waitzero(int semid,int semnum){
struct sembuf sb;
sb.sem_num=semnum;
sb.sem_op=0;
sb.sem_flg=0;
mysemop(semid,&sb,1);
}
int mysemget(key_t key,int nsems,int shmflg) {
int retval;
retval=semget(key,nsems,shmflg);
if(retval==-1) {
printf("semget key %d,nsems %d failed:%s",key,nsems,strerror(errno));
exit(255);
}
return retval;
}
int mysemctl(int semid,int semnum,int cmd,union semun arg) {
int retval;
retval=semctl(semid,semnum,cmd,arg);
if(retval==-1) {
printf("semctl semid %d,semnum %d,cmd %d failed:% s",semid,semnum,cmd,strerror(errno));
exit(255);
}
return retval;
}
int mysemop(int semid,struct sembuf *sops,unsigned nsops) {
int retval;
retval=semop(semid,sops,nsops);
if(retval==-1) {
printf("semop semid %d (%d operations) failed:%s",semid,nsops,strerror(errno));
exit(255);
}
return retval;
}
int myshmget(key_t key,int size,int shmflg) {
int retval;
retval=shmget(key,size,shmflg);
if(retval==-1) {
printf("shmget key %d,size %d failed:%s",key,size,strerror(errno));
exit(255);
}
return retval;
}
void *myshmat(int shmid,const void *shmaddr,int shmflg) {
void *retval;
retval=shmat(shmid,shmaddr,shmflg);
if(retval==(void*)-1) {
printf("shmat shmid %d failed:%s",shmid,strerror(errno));
exit(255);
}
return retval;
}
int myshmctl(int shmid,int cmd,struct shmid_ds *buf) {
int retval;
retval=shmctl(shmid,cmd,buf);
if(retval==-1) {
printf("shmctl shmid %d,cmd %d failed:%s",shmid,cmd,strerror(errno));
exit(255);
}
return retval;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -