Chinaunix首页 | 论坛 | 博客
  • 博客访问: 59902
  • 博文数量: 10
  • 博客积分: 207
  • 博客等级: 入伍新兵
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-15 14:29
文章分类

全部博文(10)

文章存档

2013年(3)

2012年(7)

分类: LINUX

2012-10-21 16:45:58

先申请共享内存,在映射到进程的私人空间,写端写入数据到这段内存,读端从这段内存读出并打印到屏幕
,再申请两个信号灯实现读写的同步,输入‘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);
 }
 }
打印结果如下:
 
阅读(2191) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~