这本是一道题:一本是一个全局变量来做的控制共享内存通信方式,一个已经实现的信号量通信,最终的结果是让这两个掺和在一起。用信号量来控制共享内存通信的读写顺序。
原本信号量通信方式的函数在这是,原本的共享内存程序在这里。
做的最新的结果是可以通信了,但是在客户端有一点点异常,就是在服务器端还没有释放信号量,但是客户端不可以获取的,这使我很疑惑。
服务器端:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
#include <sys/sem.h>
#include <signal.h>
/********************************************************/
int pid,semid;
/********************************************************/
void my_func(int sign_no)
{
if(sign_no==SIGINT)
{
printf("\nYes Sir,I have get SIGINT\n");
if(semctl(semid, 0, IPC_RMID, 0)<0)
{
printf("semctl remove semaphore set failed\n");
exit(EXIT_FAILURE);
}
printf("semctl remove semaphore set OK\n");
exit(EXIT_FAILURE);
}
}
int main(void)
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;
signal(SIGINT, my_func);
/***************************************************************/
key_t semkey;
if((semkey=ftok("/home", 1))<0)
{
printf("ftok failed\n");
exit(EXIT_FAILURE);
}
printf("ftok ok, semkey=%d\n", semkey);
if((semid=semget(semkey, 1, IPC_CREAT|0666))<0)
{
printf("semget failed\n");
exit(EXIT_FAILURE);
}
printf("semget ok, semid = %d\n", semid);
if((semctl(semid, 0, SETVAL, 1))<0)
{
printf("semctl set sermval failed\n");
exit(EXIT_FAILURE);
}
printf("semctl set semval ok\n");
struct sembuf p_op_buf, v_op_buf;
p_op_buf.sem_num=0;
p_op_buf.sem_op = -1;
/******************************************************************/
/*创建共享内存*/
shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
/*映射共享内存*/
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n",(int)shared_memory);
/*让结构体指针指向这块共享内存*/
shared_stuff=(struct shared_use_st *)shared_memory;
/*循环的向共享内存中写数据,直到写入的为“end”为止*/
while(running)
{
/******************************************************************************/
//获取信号量
if(semop(semid, &p_op_buf, 1)<0)
{
printf("semop failed\n");
exit(EXIT_FAILURE);
}
printf("shm2 get the semaphore\n");
/******************************************************************************/
printf("Ener some text:");
fgets(buffer,BUFSIZ,stdin);
strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
shared_stuff->written_by_you=1;
if(strncmp(buffer,"end",3)==0)
{
running=0; //结束循环
}
/*****************************************************************************/
//释放信号量
v_op_buf.sem_num = 0;
v_op_buf.sem_op = 1;
v_op_buf.sem_flg = 0;
if(semop(semid, &v_op_buf, 1)<0)
{
printf("semop release semaphore failed\n");
exit(EXIT_FAILURE);
}
printf("semop release semaphore ok\n");
/*****************************************************************************/
}
/*删除共享内存*/
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
客户端:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
#include <sys/sem.h>
int main(void)
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
int shmid;
/***************************************************************/
int pid,semid;
key_t semkey;
if((semkey=ftok("/home", 1))<0)
{
printf("ftok failed\n");
exit(EXIT_FAILURE);
}
printf("ftok ok, semkey=%d\n", semkey);
if((semid=semget(semkey, 0, 0))<0)
{
printf("semget failed\n");
exit(EXIT_FAILURE);
}
printf("semget ok, semid = %d\n", semid);
if((semctl(semid, 0, SETVAL, 1))<0)
{
printf("semctl set sermval failed\n");
exit(EXIT_FAILURE);
}
printf("semctl set semval ok\n");
struct sembuf p_op_buf, v_op_buf;
p_op_buf.sem_num=0;
p_op_buf.sem_op = -1;
p_op_buf.sem_flg = 0;
/******************************************************************/
/*创建共享内存*/
shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
/*映射共享内存*/
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n",(int)shared_memory);
/*让结构体指针指向这块共享内存*/
shared_stuff=(struct shared_use_st *)shared_memory;
/*控制读写顺序*/
//shared_stuff->written_by_you=0;
/*循环的从共享内存中读数据,直到读到“end”为止*/
while(running)
{
/*
if(shared_stuff->written_by_you)
{
printf("You wrote:%s",shared_stuff->some_text);
sleep(1); //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写
shared_stuff->written_by_you=0;
if(strncmp(shared_stuff->some_text,"end",3)==0)
{
running=0; //结束循环
}
}
*/
/******************************************************************************/
//获取信号量
if(semop(semid, &p_op_buf, 1)<0)
{
printf("semop failed\n");
exit(EXIT_FAILURE);
}
printf("shm1 get the semaphore\n");
/*******************************************************************************/
printf("You wrote:%s",shared_stuff->some_text);
sleep(1); //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写
if(strncmp(shared_stuff->some_text,"end",3)==0)
{
running=0; //结束循环
}
/****************************************************************************/
//释放信号量
v_op_buf.sem_num = 0;
v_op_buf.sem_op = 1;
v_op_buf.sem_flg = 0;
if(semop(semid, &v_op_buf, 1)<0)
{
printf("semop release semaphore failed\n");
exit(EXIT_FAILURE);
}
printf("semop release semaphore ok\n");
/*****************************************************************************/
}
/*******************************************************************************/
/*删除共享内存*/
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
以后的解决方案是先把那个信号量的程序由一个程序拆分成两个,彻底掌握信号量通信的过程。再来改造共享内存读写顺序。课程还要继续有机会再来解决吧!还一个实现上边 的方法参考
这里。