1.用信號量實現使用臨界區的進程間互斥
- 要求:
(1)父進程輸出O,子進程輸出X,只有一個進程能夠進入該臨界區
(2)當父進程sleep的時候,子進程也不能獲得臨界區資源,因爲父進程的P操作已經鎖定了資源,直到它釋放資源(V操作)纔可以。
同理,子進程的X也是同對出現的,不可能出現輸出奇數個X,然後被父進程搶佔輸出O
- eg:NetworkProgramming-master (1)\NetworkProgramming-master\P30sem02.cpp
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <wait.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0);
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int sem_creat(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("setval")
}
return 0;
}
int sem_getval(int semid)
{
int ret;
ret = semctl(semid, 0, GETVAL);
if (ret == -1)
{
ERR_EXIT("getval")
}
printf("sem.val = %d\n", ret);
return ret;
}
int sem_d(int semid)
{
int ret;
ret = semctl(semid, 0, IPC_RMID, NULL);
if (ret == -1)
{
ERR_EXIT("rm_sem")
}
return 0;
}
int sem_p(int semid)
{
struct sembuf sembuf;
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = 0;
int ret;
ret = semop(semid, &sembuf, 1);
if (ret == -1)
{
ERR_EXIT("sem_p")
}
return ret;
}
int sem_v(int semid)
{
struct sembuf sembuf;
sembuf.sem_num = 0;
sembuf.sem_op = 1;
sembuf.sem_flg = 0;
int ret;
ret = semop(semid, &sembuf, 1);
if (ret == -1)
{
ERR_EXIT("sem_v")
}
return ret;
}
int sem_getmode(int semid)
{
union semun su;
struct semid_ds sem;
su.buf = &sem;
int ret =semctl(semid, 0, IPC_STAT, su);
if (ret == -1)
{
ERR_EXIT("semctl");
}
printf("current permissions is %o\n", su.buf->sem_perm.mode);
return ret;
}
int sem_setmode(int semid, char* mode)
{
union semun su;
struct semid_ds sem;
su.buf = &sem;
int ret =semctl(semid, 0, IPC_STAT, su);
if (ret == -1)
{
ERR_EXIT("semctl");
}
printf("current permissions is %o\n", su.buf->sem_perm.mode);
sscanf(mode, "%o", (unsigned int*)&su.buf->sem_perm.mode);
ret = semctl(semid, 0, IPC_SET, su);
if (ret == -1)
{
ERR_EXIT("semctl");
}
printf("permission updated..\n");
return ret;
}
void print(int sigmid, char* s)
{
int i = 0;
int pause_time;
srand(getpid());
for (int i = 0; i < 10; ++i)
{
sem_p(sigmid);
printf("%s", s);
fflush(stdout);
pause_time = rand() % 3;
sleep(pause_time);
printf("%s", s);
fflush(stdout);
sem_v(sigmid);
pause_time = rand() % 2;
sleep(pause_time);
}
}
int main(int argc, char** argv)
{
int sigmid = sem_creat(IPC_PRIVATE);
sem_setval(sigmid, 0);
pid_t pid = fork();
if (pid == -1)
{
ERR_EXIT("fork");
}
if (pid > 0)
{
sem_setval(sigmid, 1);
print(sigmid, "o");
wait(nNULL);
sem_d(sigmid);
}
else
{
print(sigmid, "x");
}
return 0;
}
- 測試結果如下: