由信号灯实现通信。
发送端send.c代码:
#include <myhead.h>
#include "./sem.h"
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
int semid = semID_get(2);//创建2个信号灯
key_t key = ftok("./",'U');
if(key==-1)
{
perror("ftok");
return -1;
}
int shmID = shmget(key,PAGE_SIZE,IPC_CREAT|0664);
if(shmID==-1)
{
perror("shmget");
return -1;
}
char *sendbuff = shmat(shmID,NULL,0);//映射出共享内存
if(sendbuff==(void *)-1)
{
perror("shmat");
return -1;
}
while(1)
{
P(semid,0);//申请0号灯资源
printf("请输入你的信息:");
fgets(sendbuff,PAGE_SIZE,stdin);
sendbuff[strlen(sendbuff)-1]='\0';
V(semid,1);//释放1号灯资源
if(strcmp("quit",sendbuff)==0)
{
break;
}
}
if(shmdt(sendbuff)==-1)
{
perror("shmat");
return -1;
}
if(shmctl(shmID,IPC_RMID,NULL)==-1)
{
perror("shmctl");
return -1;
}
return 0;
}
接收端rev.c代码:
#include <myhead.h>
#include "./sem.h"
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
int semid = semID_get(2);
key_t key = ftok("./",'U');
if(key==-1)
{
perror("ftok");
return -1;
}
int shmID = shmget(key,PAGE_SIZE,IPC_CREAT|0664);
if(shmID==-1)
{
perror("shmget");
return -1;
}
char *revbuff = shmat(shmID,NULL,0);//只读
if(revbuff==(void *)-1)
{
perror("shmat");
return -1;
}
while(1)
{
P(semid,1);//申请1号灯资源
printf("%s\n",revbuff);
if(strcmp("quit",revbuff)==0)
{
break;
}
V(semid,0);//释放0号灯
}
return 0;
}
sem.c代码:
#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 sem_INFO;
printf("请输入编号为%d信号灯的值:",SEMno);
scanf("%d",&sem_INFO.val);
getchar();
if(semctl(SEMid,SEMno,SETVAL,sem_INFO)==-1)
{
perror("semtal");
return -1;
}
return 0;
}
//申请信号灯id,初始化信号灯,返回信号灯集的id
int semID_get(int SEMcount)
{
key_t key = ftok("./",'Y');
if(key==-1)
{
perror("key");
return -1;
}
int SEMid;
if((SEMid = semget(key,SEMcount,IPC_CREAT|IPC_EXCL|0664))==-1)
{
if(errno==EEXIST)
{
SEMid = semget(key,SEMcount,IPC_CREAT|0664);//已经存在直接打开即可
return SEMid;
}
perror("semget");
return -1;
}
int i;
for(i = 0;i<SEMcount;i++)
{
init_semno(SEMid,i);//初始化信号灯
}
return SEMid;
}
int P(int SEMid,int SEMno)//申请资源
{
struct sembuf SEM_op;
SEM_op.sem_num = SEMno;//要申请资源的信号灯号
SEM_op.sem_op = -1;//申请资源
SEM_op.sem_flg = 0;//阻塞方式申请信号灯
if(semop(SEMid,&SEM_op,1)==-1)//操作的灯个数
{
perror("semop P");
return -1;
}
return 0;
}
int V(int SEMid,int SEMno)//释放资源
{
struct sembuf SEM_op;
SEM_op.sem_num = SEMno;//要申请资源的信号灯号
SEM_op.sem_op = 1;//释放资源
SEM_op.sem_flg = 0;//阻塞方式申请信号灯
if(semop(SEMid,&SEM_op,1)==-1)//操作的灯个数
{
perror("semop V");
return -1;
}
return 0;
}
int DEL_sem(int SEMid)
{
if(semctl(SEMid,0,IPC_RMID)==-1)
{
perror("smectl");
return -1;
}
return 0;
}
sem.h代码:
#ifndef _SEM_H_
#define _SEM_H_
//申请信号等集,返回信号灯集的id
int semID_get(int semno);//semno要设置灯的个数
//申请信号灯资源(value设置为0)
int P(int semID,int semno);//参数1:信号灯id,参数2灯的个数
//释放信号灯资源(value设置为1)
int V(int semID,int semno);
//删除信号灯集
int dele_sem(int semID);
#endif
运行结果: