第三十一章 System V信号量(二)
用信号量实现进程互斥示例
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0)
int sem_create(key_t key)
{
int semid;
semid = semget(key, 1, IPC_CREAT|IPC_EXCL| 0666);
if(semid == -1)
ERR_EXIT("semget");
return semid;
}
int sem_open(key_t key)
{
int semid;
semid = semget(key, 0, 0);
if(semid == -1)
ERR_EXIT("semget");
return semid;
}
int sem_setval(int semid, int val)
{
union semun su;
su.val = val;
int ret;
ret = semctl(semid, 0, SETVAL, su);
if(ret == -1)
ERR_EXIT("semctl");
return 0;
}
int sem_del(int semid)
{
int ret;
ret = semctl(semid, 0, IPC_RMID, 0);
if(ret == -1)
ERR_EXIT("semctl");
return 0;
}
int sem_getval(int semid, int val)
{
int ret;
ret = semctl(semid, 0, GETVAL, 0);
if(ret == -1)
ERR_EXIT("semctl getval");
return ret;
}
int sem_p(int semid)
{
struct sembuf sops = {0, -1, 0};
int ret;
ret = semop(semid, &sops, 1);
if(ret == -1)
ERR_EXIT("semop");
return 0;
}
int sem_v(int semid)
{
struct sembuf sops = {0, 1, 0};
int ret;
ret = semop(semid, &sops, 1);
if(ret == -1)
ERR_EXIT("semop");
return 0;
}
int semid;
void print(char ch)
{
int pause_time;
srand(getpid());
int i;
for(i=0; i < 10; ++i)
{
sem_p(semid);
printf("%c", ch);
fflush(stdout);
pause_time = rand() % 3;
sleep(pause_time);
printf("%c", ch);
//fflush(stdin)刷新标准输入缓冲区,把输入缓冲区里的东西丢弃[非标准]
//fflush(stdout)刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上
fflush(stdout);
sem_v(semid);
pause_time = rand() % 2;
sleep(pause_time);
}
}
int main(int argc, char* argv[])
{
semid = sem_create(IPC_PRIVATE);
sem_setval(semid, 0);
pid_t pid;
pid = fork();
if(pid == -1)
ERR_EXIT("fork");
if(pid > 0)
{
sem_setval(semid,1);
print('O');
wait(NULL);
sem_del(semid);
}
else
{
print('X');
}
return 0;
}
结果
./semget
OOXXOOXXOOXXXXOOXXOOXXOOXXOOXXOOXXOOXXOO
./semget
OOXXOOXXOOXXOOXXOOXXOOXXOOXXOOXXOOXXOOXX