#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define SHM_KEY 0x33
#define SEM_KEY 0x44
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int P(int semid)
{
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
if(semop(semid, &sb, 1) == -1) {
perror("semop");
return -1;
}
return 0;
}
int V(int semid)
{
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = SEM_UNDO;
if(semop(semid, &sb, 1) == -1) {
perror("semop");
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
pid_t pid;
int i, shmid, semid;
int *ptr;
union semun semopts;
/* 创建一块共享内存, 存一个int变量 */
if ((shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0600)) == -1) {
perror("msgget");
}
/* 将共享内存映射到进程, fork后子进程可以继承映射 */
if ((ptr = (int *)shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat");
}
*ptr = 0;
/* 创建一个信号量用来同步共享内存的操作 */
if ((semid = semget(SEM_KEY, 1, IPC_CREAT | 0600)) == -1) {
perror("semget");
}
/* 初始化信号量 */
semopts.val = 1;
if (semctl(semid, 0, SETVAL, semopts) < 0) {
perror("semctl");
}
if ((pid = fork()) < 0) {
perror("fork");
} else if (pid == 0) { /* Child */
/* 子进程对共享内存加1 */
for (i = 0; i < 100000; i++) {
P(semid);
(*ptr)++;
V(semid);
printf("child: %d\n", *ptr);
}
} else { /* Parent */
/* 父进程对共享内存减1 */
for (i = 0; i < 100000; i++) {
P(semid);
(*ptr)--;
V(semid);
printf("parent: %d\n", *ptr);
}
waitpid(pid);
/* 如果同步成功, 共享内存的值为0 */
printf("finally: %d\n", *ptr);
}
return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <stdlib.h>
#define SHM_KEY 0x33
int main(int argc, char **argv)
{
pid_t pid;
int i, shmid;
int *ptr;
sem_t *sem;
/* 创建一块共享内存, 存一个int变量 */
if ((shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0600)) == -1) {
perror("msgget");
}
/* 将共享内存映射到进程, fork后子进程可以继承映射 */
if ((ptr = (int *)shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat");
}
*ptr = 0;
/* posix的有名信号量是kernel persistent的
* 调用sem_unlink删除以前的信号量 */
sem_unlink("/mysem");
/* 创建新的信号量, 初值为1, sem_open会创建共享内存
* 所以信号量是内核持续的 */
if ((sem = sem_open("/mysem", O_CREAT, 0600, 1)) == SEM_FAILED) {
perror("sem_open");
}
if ((pid = fork()) < 0) {
perror("fork");
} else if (pid == 0) { /* Child */
/* 子进程对共享内存加1 */
for (i = 0; i < 100000; i++) {
sem_wait(sem);
(*ptr)++;
sem_post(sem);
printf("child: %d\n", *ptr);
}
} else { /* Parent */
/* 父进程对共享内存减1 */
for (i = 0; i < 100000; i++) {
sem_wait(sem);
(*ptr)--;
sem_post(sem);
printf("parent: %d\n", *ptr);
}
waitpid(pid);
/* 如果同步成功, 共享内存的值为0 */
printf("finally: %d\n", *ptr);
sem_unlink("/mysem");
}
return 0;
}
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
int main (int argc, char **argv)
{
key_t ipckey;
int semid;
/*建立两个信号灯结构*/
struct sembuf sem[2]; /* sembuf defined in sys/sem.h */
/* 创建IPC Key */
ipckey = ftok("/tmp/rich", 42);
/* 创建信号量. 4 == READ, 2 == ALTER */
semid = semget(ipckey, 1, 0666 | IPC_CREAT);
if (semid < 0)
{
printf("Error - %sn", strerror(errno));
_exit(1);
}
/*设置*/
/* These never change so leave them outside the loop */
sem[0].sem_num = 0;
sem[1].sem_num = 0;
sem[0].sem_flg = SEM_UNDO; /* Release semaphore on exit */
sem[1].sem_flg = SEM_UNDO; /* Release semaphore on exit */
while(1)
{
printf("[%s] Waiting for the semaphore to be releasedn\n", argv[1]);
/* 设置两个信号灯,灯1等待,灯2请求资源锁 */
sem[0].sem_op = 0; /* Wait for zero */
sem[1].sem_op = 1; /* Add 1 to lock it*/
/*设置信号量集,两个信号量*/
semop(semid, sem, 2);
/*资源锁区*/
printf("[%s] I have the semaphoren\n", argv[1]);
sleep(rand() % 3);
/* Critical section, sleep for 0-2 seconds */
sem[0].sem_op = -1; /* Decrement to unlock */
/*出锁,对信号量1操作*/
semop(semid, sem, 1);
printf("[%s] Released semaphoren\n", argv[1]);
sleep(rand() % 3); /* Sleep 0-2 seconds */
}
}
#include "all.h"
/* 每个字符输出的间隔时间 */
#define TEN_MILLION 5000000L
#define BUFSIZE 1024
void *threadout(void *args);
int main(int argc, char *argv[])
{
int error;
int i;
int n;
sem_t semlock;
pthread_t *tids;
if (argc != 2) {
fprintf (stderr, "Usage: %s numthreads\n", argv[0]);
return 1;
}
n = atoi(argv[1]);
tids = (pthread_t *)calloc(n, sizeof(pthread_t));
if (tids == NULL) {
perror("Failed to allocate memory for thread IDs");
return 1;
}
if (sem_init(&semlock, 0, 1) == -1) {
perror("Failed to initialize semaphore");
return 1;
}
for (i = 0; i < n; i++) {
if (error = pthread_create(tids + i, NULL, threadout, &semlock)) {
fprintf(stderr, "Failed to create thread:%s\n", strerror(error));
return 1;
}
}
for (i = 0; i < n; i++) {
if (error = pthread_join(tids[i], NULL)) {
fprintf(stderr, "Failed to join thread:%s\n", strerror(error));
return 1;
}
}
return 0;
}
void *threadout(void *args)
{
char buffer[BUFSIZE];
char *c;
sem_t *semlockp;
struct timespec sleeptime;
semlockp = (sem_t *)args;
sleeptime.tv_sec = 0;
sleeptime.tv_nsec = TEN_MILLION;
snprintf(buffer, BUFSIZE, "This is thread from process %ld\n",
(long)getpid());
c = buffer;
/****************** entry section *******************************/
while (sem_wait(semlockp) == -1)
if(errno != EINTR) {
fprintf(stderr, "Thread failed to lock semaphore\n");
return NULL;
}
/****************** start of critical section *******************/
while (*c != '\0') {
fputc(*c, stderr);
c++;
nanosleep(&sleeptime, NULL);
}
/****************** exit section ********************************/
if (sem_post(semlockp) == -1)
fprintf(stderr, "Thread failed to unlock semaphore\n");
/****************** remainder section ***************************/
return NULL;
}