zoukankan      html  css  js  c++  java
  • 信号量

    信号量是不同进程间同步的方式。当几个不同的进程同时访问临界区时,需要同步,防止多个进程同时篡改数据,或者读到脏数据。

    sem_wait对信号量减一,sem_post对信号量加一。

    当初始化信号量值为1时, sem_wait类似于加锁,sem_post类似于释放锁.

    在前面共享内存的代码上稍作修改加上信号量的部分,来保护共享内存。

    其中写共享内存的代码mmap_write.c如下:

    #include <stdio.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <semaphore.h>

    typedef struct _ShareMem{
      char str[128];
      int val;
    }ShareMem;
    #define SHM_STR "FELLOW_SHARE_SOMETHING"
    #define FELLOW_SEM "fellow-sem"
    void main(void)
    {
      int fd;
      ShareMem *mem;
      sem_t *sem;
      if (SEM_FAILED == (sem = sem_open(FELLOW_SEM,O_CREAT, 0666, 1)))//初始化信号量为1    
      {
        printf("sem_open fail:%d,%s ",errno,strerror(errno));
      }

      fd = shm_open(SHM_STR, O_RDWR | O_CREAT, 0666);
      if (-1 == fd)
      {
        printf("shm_open fail:%d,%s ",errno,strerror(errno));
      }
      ftruncate(fd, sizeof(ShareMem));
      mem = mmap(NULL, sizeof(ShareMem), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
      if (mem == MAP_FAILED)
      {
        printf("mmap fail:%d,%s ",errno,strerror(errno));
      }


      printf("share mem:0x%x ", (int)mem);
      sem_wait(sem);
      printf("write share mem now, please wait.... ");
      strncpy(mem->str, "fellow", strlen("fellow"));
      mem->val = 10000;
      sleep(10);
      sem_post(sem);
      printf("write share mem done, you can read now.... ");
      close(fd);
    }

    读共享内存的代码mmap_read.c如下:

    #include <stdio.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    #include <errno.h>
    #include <semaphore.h>
    typedef struct _ShareMem{
      char str[128];
      int val;
    }ShareMem;
    #define SHM_STR "FELLOW_SHARE_SOMETHING"
    #define FELLOW_SEM "fellow-sem"
    void main(void)
    {
      int fd;
      ShareMem *mem;
      sem_t *sem;
      if (SEM_FAILED == (sem = sem_open(FELLOW_SEM, O_CREAT, 0666, 1)))
      {
      printf("sem_open fail: %d, %s ", errno, strerror(errno));
      }
      int val = -1;
      sem_getvalue(sem, &val);
      printf("sem value:%d ", val);


      fd = shm_open(SHM_STR, O_RDONLY, 0666);
      if (-1 == fd)
      {
        printf("shm_open fail: %d, %s ", errno, strerror(errno));
      }
      mem = mmap(NULL, sizeof(ShareMem), PROT_READ, MAP_SHARED, fd, 0);
      if (MAP_FAILED == mem)
      {
        printf("mmap fail: %d, %s ", errno, strerror(errno));
      }
      sem_wait(sem);
      printf("share mem:0x%x,str:%s,val:%d ", (int)mem, mem->str, mem->val);
      sem_post(sem);
      close(fd);
      munmap(mem, sizeof(ShareMem));
      shm_unlink(SHM_STR);
      sem_unlink(FELLOW_SEM);
    }

    先执行mmap_write,再自行mmap_read,假设写操作经历10s中,可以看到在这10s期间,mmap_read一直在等信号量释放。

  • 相关阅读:
    MySQL客户端管理
    Windows10安装Pytorch环境要点
    使用ssh加密github通信
    JVM 对象状态判断01
    并发之AbstractQueuedLongSynchronize----AQS
    关于CountDownLatch控制线程的执行顺序
    关于线程执行顺序的问题
    并发之Striped64(l累加器)
    并发之线程以及线程的中断状态
    1 JPA入门----项目搭建以及CRUD
  • 原文地址:https://www.cnblogs.com/fellow1988/p/6151777.html
Copyright © 2011-2022 走看看