信号灯的典型应用



二值信号灯:值为0或1.与互斥锁类似,资源可用时值为1,不可用时值为0。
程序如下:
读端
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h>
#include <string.h>
#include <strings.h>
int wait(void)
{
     int semid = -1;
     int ret = -1;
     key_t key = ftok("/home",2);
     if ( -1 == key )
     {
          perror("ftok");
          return -1;
     }
     semid = semget(key,2,0666|IPC_CREAT|IPC_EXCL);//获得信号灯ID。包含2个信号灯
     if ( -1 == semid )
     {
          if( EEXIST == errno )
          {
               semid = semget(key,2,0666);
               if (-1 == semid )
               {
                    perror("semget");
                    return -1;
               }
          }else
          {
               perror("semget");
               return -1;
          }
     }
     struct sembuf buf;
     bzero(&buf,sizeof(struct sembuf));
     buf.sem_num = 0;
     buf.sem_op = -1;//分配资源,p操作
     buf.sem_flg = 0;
     ret = semop(semid,&buf,1);//要操作一个信号灯,信号灯编号为0,操作时分配资源。使资源不可用。锁住
     if ( -1 == ret )
     {
          perror("semop");
          return -1;
     }
}


char *addr=NULL;
void fun(int arg)
{
     printf("%s\n",addr);
}    
int main(int argc,char **argv)
{
     int ret = -1;
     int shmid = -1;
     //char *addr = NULL;

     signal(2,fun);
     key_t key = ftok("/",1);//获得key值
     if ( -1 == key )
     {
          perror("ftok");
          return -1;
     }
     shmid = shmget(key,4096,0666|IPC_CREAT|IPC_EXCL);//设置共享内存大小为4096
     if ( -1 == shmid )
     {
          if (EEXIST == errno)
          {
               shmid = shmget(key,4096,0666);
               if (-1 == shmid)
               {
                    perror("shmget 2");
                    return -1;
               }
          }
          else
          {
               perror("shmget");
          }
     }
     addr = shmat(shmid,NULL,0);//获得共享内存的空间地址
     if ( (void*)(-1) == addr )
     {
          perror("shmat");
          return -1;
     }
     while(1)
     {
          wait();//v操作,分配资源,使共享内存资源减1;使资源不可用
          //--
          printf("%s",addr);
     }
     ret = shmdt(addr);
     if ( -1 == ret )
     {
          perror("shmdt");
          return -1;
     }

     printf("%ld\n",key);
     return 0;
}


写端
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h>
#include <string.h>
#include <strings.h>
int semid = -1;
int fun_init(void)
{
     int ret = -1;
     key_t key = ftok("/home",2);//获得key值
     if ( -1 == key )
     {
          perror("ftok");
          return -1;
     }
     semid = semget(key,2,0666|IPC_CREAT|IPC_EXCL);//获得信号灯ID。包含2个信号灯
     if ( -1 == semid )
     {
          if( EEXIST == errno )
          {
               semid = semget(key,2,0666);
               if (-1 == semid )
               {
                    perror("semget");
                    return -1;
               }
          }else
          {
               perror("semget");
               return -1;
          }
     }
#if 1
     ret = semctl(semid,0,SETVAL,0);//要修改的信号灯编号为0,SETVAL设置信号灯的值,值为0
     if ( -1 == ret )
     {
          perror("semctl");
          return -1;
     }
#endif
     return 0;
}
int post(void)
{
     int ret = -1;
     struct sembuf buf;
     bzero(&buf,sizeof(struct sembuf));//将buf清零
     buf.sem_num = 0;//要操作的信号灯编号为0
     buf.sem_op = 1;//释放资源,V操作
     buf.sem_flg = 0;//不知什么意思
     ret = semop(semid,&buf,1);//要操作一个信号灯,信号灯编号为0,操作时释放资源,释放资源。使资源可用。解锁,使读端可以读
     if ( -1 == ret )
     {
          perror("semop");
          return -1;
     }
}
int main(int argc,char **argv)
{
     pid_t pid_r = -1;
     int ret = -1;
     int shmid = -1;
     char *addr = NULL;
     key_t key = ftok("/",1);//获得key值
     if ( -1 == key )
     {
          perror("ftok");
          return -1;
     }
     shmid = shmget(key,4096,0666|IPC_CREAT|IPC_EXCL);//共享内存的大小设为4096
     if ( -1 == shmid )
     {
          if (EEXIST == errno)
          {
               shmid = shmget(key,4096,0666);
               if (-1 == shmid)
               {
                    perror("shmget 2");
                    return -1;
               }
          }
          else
          {
               perror("shmget");
          }
     }
     addr = shmat(shmid,NULL,0);//将共享内存映射到addr,0为共享内存可读可写
     if ( (void*)(-1) == addr )
     {
          perror("shmat");
          return -1;
     }
     ret = fun_init();//初始化信号灯,灯值为0
     if ( -1 == ret )
     {
          perror("fun_init");
          return -1;
     }
     //0
     while(1)
     {
          fgets(addr,4096,stdin);//获得消息
          //++
          ret = post();//V操作,将值加1.释放资源,外部资源就加1;信号灯的值为1,资源可用
          if( -1 == ret)
          {
               perror("post");
               return -1;
          }
     }

     ret = shmdt(addr);//删除共享内存映射后的地址
     if ( -1 == ret )
     {
          perror("shmdt");
          return -1;
     }

     printf("%ld\n",key);
     return 0;
}
posted @ 2013-11-04 22:57  vonyao  阅读(264)  评论(0编辑  收藏  举报