struct PGPROC
{
...
PGSemaphore sem;
... | -------- 是否共享,如果是需要在共享内存中获取newsem
}; | |
v v v----------- 初始值:1
if (sem_init(newsem, 1, 1) < 0)
...
POSIX相比SYSTEM V接口的优势:
POSIX相对SYSTEM V接口的劣势:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
#define PG_CACHE_LINE_SIZE 128
#define PG_SEM_REF(x) (&(x)->sem_padded.pgsem)
typedef union SemTPadded
{
sem_t pgsem;
char pad[PG_CACHE_LINE_SIZE];
} SemTPadded;
typedef struct PGSemaphoreData
{
SemTPadded sem_padded;
} PGSemaphoreData;
typedef struct PGSemaphoreData *PGSemaphore;
static PGSemaphore sharedSemas;
int main(int argc, char *argv[])
{
sem_t *newsem;
int errStatus;
sharedSemas = mmap(NULL, sizeof(PGSemaphoreData), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (sharedSemas == MAP_FAILED)
{
fprintf(stderr, "mmap() failed\n");
exit(EXIT_FAILURE);
}
newsem = PG_SEM_REF(sharedSemas);
if (sem_init(newsem, 1, 1) < 0)
{
fprintf(stderr, "sem_init() failed\n");
exit(EXIT_FAILURE);
}
sem_wait(newsem);
/*Parent and child share mapping*/
switch (fork())
{
case -1:
fprintf(stderr, "fork() failed\n");
exit(EXIT_FAILURE);
case 0:
printf("[child]mmap address %p\n", sharedSemas);
do
{
printf("[child]sem_post...\n");
errStatus = sem_post(newsem);
} while (errStatus < 0 && errno == EINTR);
printf("[child]exit\n");
exit(EXIT_SUCCESS);
default:
printf("[parent]mmap address %p\n", sharedSemas);
do
{
printf("[parent]start semi_wait...\n");
errStatus = sem_wait(newsem);
} while (errStatus < 0 && errno == EINTR);
printf("[parent]stop semi_wait...\n");
if (wait(NULL) == -1)
{
fprintf(stderr, "wait() failed\n");
exit(EXIT_FAILURE);
}
printf("[parent]stop waiting child exit\n");
if (munmap(sharedSemas, sizeof(int)) == -1)
{
fprintf(stderr, "munmap() failed\n");
exit(EXIT_FAILURE);
}
printf("[parent]exit\n");
exit(EXIT_SUCCESS);
}
}
// gcc -o main1 -Wall -g -ggdb -O0 -g3 -gdwarf-2 main1.c -lpthread
执行结果:
[parent]mmap address 0x7f69797d4000
[parent]start semi_wait...
[child]mmap address 0x7f69797d4000
[child]sem_post...
[child]exit
[parent]stop semi_wait...
[parent]stop waiting child exit
[parent]exit
组提交中充当读barrier:
LWLock中锁队列的唤醒:
轻量锁是自带所队列的,等锁的进程会按顺序唤醒,等锁的进程都是等在信号量上了。