您的位置:首页 > 运维架构 > Linux

信号灯的典型应用

2013-11-04 22:57 225 查看


二值信号灯:值为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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 信号灯