先申请共享内存,在映射到进程的私人空间,写端写入数据到这段内存,读端从这段内存读出并打印到屏幕
,再申请两个信号灯实现读写的同步,输入‘quit’退出,并删除共享内存映射,删除共享内存,删除信号灯后并退出,程序如下:
#include
#include
#include
#include
#include
#include
#include
#define SHM_SIZE 1024
#define SEM_N 2
#define W 1 //写操作的信号灯
#define R 0 //读操作的信号灯
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_sharememory(char *pathname) //初始化共享内存函数
{
key_t key;
int shmid;
if((key = ftok(pathname,'a')) < 0)
{
perror("Fail to ftok");
exit(EXIT_FAILURE);
}
if((shmid = shmget(key,SHM_SIZE,IPC_CREAT | 0666)) < 0)
{
/* if(errno == EEXIST)
{
if((shmid = shmget(key,SHM_SIZE,IPC_CREAT | 0666)) < 0)
{
perror("Fail to shmget");
exit(EXIT_FAILURE);
}
}
*/
perror("Fail to shmget");
exit(EXIT_FAILURE);
}
return shmid;
}
int set_value(int semid,int num,int val) //给信号灯赋值函数
{
union semun sem_un;
sem_un.val = val;
if(semctl(semid,num,SETVAL,sem_un) < 0)
{
perror("Fail to semctl");
exit(EXIT_FAILURE);
}
return 0;
}
int init_semaphore(char *pathname)//初始化信号灯函数
{
key_t key;
int semid;
if((key = ftok(pathname,'a')) < 0)
{
perror("Fail to ftok");
exit(EXIT_FAILURE);
}
if((semid = semget(key,SEM_N,IPC_CREAT | 0666)) < 0)
{
perror("Fail to semget");
exit(EXIT_FAILURE);
}
printf("semid = %d\n",semid);
set_value(semid,W,1);
set_value(semid,R,0);
return semid;
}
int P(int semid,int num) //封装的P操作函数,申请资源
{
struct sembuf sem;
sem.sem_num = num;
sem.sem_op = -1; //P操作
sem.sem_flg = 0;
if(semop(semid,&sem,1) < 0)
{
perror("Fail to semop");
exit(EXIT_FAILURE);
}
return 0;
}
int V(int semid,int num) //封装的V操作函数,释放资源
{
struct sembuf sem;
sem.sem_num = num;
sem.sem_op = 1;//V操作
sem.sem_flg = 0;
if(semop(semid,&sem,1) < 0)
{
perror("Fail to semop");
exit(EXIT_FAILURE);
}
return 0;
}
int main(int argc,char *argv[])
{
int shmid,semid;
char *addr;
if(argc < 2)
{
fprintf(stderr,"Usage %s argv[1]\n",argv[0]);
exit(EXIT_FAILURE);
}
shmid = init_sharememory(argv[1]); //初始化共享内存
if((addr = (char *)shmat(shmid,NULL,0)) < 0) //映射共享内存到自己系统默认的空间
{
perror("Fail to shmat");
exit(EXIT_FAILURE);
}
semid = init_semaphore(argv[1]); //初始化信号灯
while(1)
{
P(semid,R); //申请读资源
printf("%s\n",addr);//打印到屏幕
if(strncmp(addr,"quit",4) == 0)//如果收到'quit'退出
{
if(shmdt(addr) < 0) //删除读端映射
{
perror("Fail to shmdt");
exit(EXIT_FAILURE);
}
if(shmctl(shmid,IPC_RMID,addr) < 0)//删除共享内存
{
perror("Fail to shmctl");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
V(semid,W);//释放写资源
}
exit(EXIT_SUCCESS);
}
写端的前面部分基本是一样的,只是主函数里while循环里不一样,故列在下面:
while(1)
{
P(semid,W);//申请写资源
printf(">");
fgets(addr,SHM_SIZE,stdin);//从终端输入
addr[strlen(addr) - 1] = '\0';//处理最后的回车字符
V(semid,R);//释放读资源
if(strncmp(addr,"quit",4) == 0)
{
if(shmdt(addr) < 0) //删除写端的共享内存映射
{
perror("Fail to shmdt");
exit(EXIT_FAILURE);
}
if(semctl(semid,2,IPC_RMID) < 0)//删除信号灯
{
perror("Fail to semctl");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
打印结果如下:
阅读(2200) | 评论(0) | 转发(0) |