信号量
信号量是不同进程间同步的方式。当几个不同的进程同时访问临界区时,需要同步,防止多个进程同时篡改数据,或者读到脏数据。
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\n",errno,strerror(errno));
}
fd = shm_open(SHM_STR, O_RDWR | O_CREAT, 0666);
if (-1 == fd)
{
printf("shm_open fail:%d,%s\n",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\n",errno,strerror(errno));
}
printf("share mem:0x%x\n", (int)mem);
sem_wait(sem);
printf("write share mem now, please wait....\n");
strncpy(mem->str, "fellow", strlen("fellow"));
mem->val = 10000;
sleep(10);
sem_post(sem);
printf("write share mem done, you can read now....\n");
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\n", errno, strerror(errno));
}
int val = -1;
sem_getvalue(sem, &val);
printf("sem value:%d\n", val);
fd = shm_open(SHM_STR, O_RDONLY, 0666);
if (-1 == fd)
{
printf("shm_open fail: %d, %s\n", errno, strerror(errno));
}
mem = mmap(NULL, sizeof(ShareMem), PROT_READ, MAP_SHARED, fd, 0);
if (MAP_FAILED == mem)
{
printf("mmap fail: %d, %s\n", errno, strerror(errno));
}
sem_wait(sem);
printf("share mem:0x%x,str:%s,val:%d\n", (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一直在等信号量释放。