Chinaunix首页 | 论坛 | 博客
  • 博客访问: 702161
  • 博文数量: 152
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1793
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 12:26
个人简介

相信自己,只有不想做的,没有做不到的。

文章分类

全部博文(152)

文章存档

2021年(1)

2015年(2)

2014年(74)

2013年(75)

分类: LINUX

2013-12-16 22:32:19

信号灯集是配合共享内存实现同步和互斥的机制。
1,创建信号灯集
   semget();
2,初始化信号灯集的信号灯的值 
semctl();
3;信号灯集的P操作
semop(int semid,sturct sembuf *opstr,size_t nops)
sturct sembuf *opstr为系统结构体
semid为信号灯集ID
struct sembuf{
short sem_num;
shirt sem_op:         0 等待
                           1 释放 V操作
                           -1 分配 P操作

short sem_flg     0  阻塞等待信号到来 
                        IPC_NOWAIT  非阻塞不等待信号到来
                        SEM_LNDO 当前进程非法退出,把信号量的值还原到原先的状态

nops: 要操作的信号灯的个数
}


4,删除信号灯操作
int semctl(semid,int semnum IPC_RMID);   //IPC_RMID从系统中删除信号灯集合




read和write两个进程通信使用信号灯集配合共享内存的机制

read.c代码如下

#include
#include
#include
#include
#include
#include
#include

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_sem_value(int sem_id,int num,int value)
{
 union semun var;
 
 var.val = value;

 if(semctl(sem_id,num,SETVAL,var) < 0)
 {
  perror("Fail to semctl");
  exit(EXIT_FAILURE);
 }

 return 0;
}

//P操作
void P(int sem_id,int num)
{
 struct sembuf buf;

 buf.sem_num = num;
 buf.sem_op = -1;

 //SEM_UNDO  :值的是进程异常退出的时候,释放它申请的资源
 //IPC_NOWAIT:没有申请到资源的时候,不阻塞,立即返回
 //0         :阻塞方式
 buf.sem_flg = 0;

 if(semop(sem_id,&buf,1) < 0)
 {
  perror("Fail to semop");
  exit(EXIT_FAILURE);
 }
 
 return ;
}


//V操作
void V(int sem_id,int num)
{
 struct sembuf buf;

 buf.sem_num = num;
 buf.sem_op = 1;

 //SEM_UNDO  :值的是进程异常退出的时候,释放它申请的资源
 //IPC_NOWAIT:没有申请到资源的时候,不阻塞,立即返回
 //0         :阻塞方式
 buf.sem_flg = 0;

 if(semop(sem_id,&buf,1) < 0)
 {
  perror("Fail to semop");
  exit(EXIT_FAILURE);
 }
 
 return ;
}

//./a.out .
int main(int argc, const char *argv[])
{
 char *addr;
 int shm_id;
 key_t key;
 
 //先运行
 if((key = ftok(argv[1],'k'))  < 0)
 {
  perror("Fail to key");
  exit(EXIT_FAILURE);
 }

 printf("key = %#x.\n",key);

    /*
  *int shmget(key_t key, size_t size, int shmflg);
  *第一个参数:
  *1.IPC_PRIVATE,每次都会获得一个新的共享内存,主要用于有亲缘关系的进程
  *2.通过ftok函数获得            
  * key_t key;
  * key = ftok(pathname,字符);
  *
  *第二个参数:
  *共享内存大小
  *
  *第三个参数:
  *IPC_CREAT,IPC_EXCL,权限
  */
 //如果对应的key的共享内存不存在,创建,然后返回其ID
 //如果对应的key的共享内存存在,直接返回ID
 if((shm_id = shmget(key,1024,IPC_CREAT | 0666)) < 0)
 {
  perror("Fail to shmget");
  exit(EXIT_FAILURE);
 }

 printf("shm_id = %d.\n",shm_id);
  
 //映射共享内存
 if( (    addr = (char *)shmat(shm_id,NULL,0)   )   == (char *)-1  )
 {
  perror("Fail to shmat");
  exit(EXIT_FAILURE);
 }
 
 
 //**************************信号灯集*******************
 int sem_id;

 //创建信号灯集
 if((sem_id = semget(key,2,IPC_CREAT | IPC_EXCL | 0666) ) < 0)
 {
    if((sem_id = semget(key,2,IPC_CREAT | 0666)) < 0)
    {
     perror("Fail to semget");
     exit(EXIT_FAILURE);
    }

 }else{
  //初始化信号灯集信号灯的值
  init_sem_value(sem_id,0,0); 
  init_sem_value(sem_id,1,1);
 }

 while(1)
 {
  P(sem_id,0);

  printf("%s.\n",addr);
  
  V(sem_id,1);

  if(strncmp(addr,"quit",4) == 0)
   break;
 }

 //解除映射
 if(shmdt(addr) < 0)
 {
  perror("Fail to shmdt");
  exit(EXIT_FAILURE);
 }

 exit(EXIT_SUCCESS);;
}


write.c代码如下:

#include
#include
#include
#include
#include
#include
#include

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_sem_value(int sem_id,int num,int value)
{
 union semun var;
 
 var.val = value;

 if(semctl(sem_id,num,SETVAL,var) < 0)
 {
  perror("Fail to semctl");
  exit(EXIT_FAILURE);
 }

 return 0;
}

//P操作
void P(int sem_id,int num)
{
 struct sembuf buf;

 buf.sem_num = num;
 buf.sem_op = -1;

 //SEM_UNDO  :值的是进程异常退出的时候,释放它申请的资源
 //IPC_NOWAIT:没有申请到资源的时候,不阻塞,立即返回
 //0         :阻塞方式
 buf.sem_flg = 0;

 if(semop(sem_id,&buf,1) < 0)
 {
  perror("Fail to semop");
  exit(EXIT_FAILURE);
 }
 
 return ;
}


//V操作
void V(int sem_id,int num)
{
 struct sembuf buf;

 buf.sem_num = num;
 buf.sem_op = 1;

 //SEM_UNDO  :值的是进程异常退出的时候,释放它申请的资源
 //IPC_NOWAIT:没有申请到资源的时候,不阻塞,立即返回
 //0         :阻塞方式
 buf.sem_flg = 0;

 if(semop(sem_id,&buf,1) < 0)
 {
  perror("Fail to semop");
  exit(EXIT_FAILURE);
 }
 
 return ;
}

//./a.out .
int main(int argc, const char *argv[])
{
 char *addr;
 int shm_id;
 key_t key;
 
 //先运行
 if((key = ftok(argv[1],'k'))  < 0)
 {
  perror("Fail to key");
  exit(EXIT_FAILURE);
 }

 printf("key = %#x.\n",key);

    /*
  *int shmget(key_t key, size_t size, int shmflg);
  *第一个参数:
  *1.IPC_PRIVATE,每次都会获得一个新的共享内存,主要用于有亲缘关系的进程
  *2.通过ftok函数获得            
  * key_t key;
  * key = ftok(pathname,字符);
  *
  *第二个参数:
  *共享内存大小
  *
  *第三个参数:
  *IPC_CREAT,IPC_EXCL,权限
  */
 //如果对应的key的共享内存不存在,创建,然后返回其ID
 //如果对应的key的共享内存存在,直接返回ID
 if((shm_id = shmget(key,1024,IPC_CREAT | 0666)) < 0)
 {
  perror("Fail to shmget");
  exit(EXIT_FAILURE);
 }

 printf("shm_id = %d.\n",shm_id);
  
 //映射共享内存
 if( (    addr = (char *)shmat(shm_id,NULL,0)   )   == (char *)-1  )
 {
  perror("Fail to shmat");
  exit(EXIT_FAILURE);
 }

 //**************************信号灯集*******************
 int sem_id;

 //创建信号灯集
 if((sem_id = semget(key,2,IPC_CREAT | IPC_EXCL | 0666) ) < 0)
 {
    if((sem_id = semget(key,2,IPC_CREAT | 0666)) < 0)
    {
     perror("Fail to semget");
     exit(EXIT_FAILURE);
    }

 }else{
  //初始化信号灯集信号灯的值
  init_sem_value(sem_id,0,0); 
  init_sem_value(sem_id,1,1);
 }

 while(1)
 {
  P(sem_id,1);

  fgets(addr,1024,stdin);
  
  V(sem_id,0);

  if(strncmp(addr,"quit",4) == 0)
   break;
 }

 //解除映射
 if(shmdt(addr) < 0)
 {
  perror("Fail to shmdt");
  exit(EXIT_FAILURE);
 }

 //删除共享内存对象
 //真正删除:在共享内存映射次数为0的时候,才会删除
 if(shmctl(shm_id,IPC_RMID,NULL) < 0)
 {
  perror("Fail to shmctl");
  exit(EXIT_FAILURE);
 }
 
 usleep(500);

 //删除信号灯集合
 if(semctl(sem_id,0,IPC_RMID) < 0)
 {
  perror("Fail to semctl");
  exit(EXIT_FAILURE);
 }

 exit(EXIT_SUCCESS);;
}

阅读(2007) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~