信号量

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

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一直在等信号量释放。

原文地址:https://www.cnblogs.com/fellow1988/p/6151777.html