互斥量(mutex)可以解决多线程间对共有数据访问时的资源竞争问题,但是mutex只能在线程间使用,为解决进程间对共有资源的访问,可以使用信号量semaphore替代mutex,以下例程fence.c程序用semaphore实现了多进程对公共资源的同时访问,通过信号量实现了栅栏效应。
信号量是一个整数数组,程序中共使用7个信号量,第0-5个信号量用于控制子进程输出数字(1号子进程输出1,2号子进程输出2,...),第6个信号量用于通知父进程子进程已输出完成,并且一直等最慢的子进程完成了,父进程才能再次释放1次0-5个信号量,父进程累计释放6次,每个子进程输出6次。
-
/*栅栏效应,父进程等5个子进程中运行最慢的子进程释放资源后,才会再一次释放信号量,让子进程再次工作*/
-
#include <sys/types.h>
-
#include <sys/ipc.h>
-
#include <sys/sem.h>
-
#include <sys/wait.h>
-
#include <unistd.h>
-
-
#include <stdio.h>
-
#include <stdlib.h>
-
-
#define CHILD_NR 6
-
#define SEM_NUM (CHILD +1)
-
static void child(int semid, int num)
-
{
-
struct sembuf my_buf, p_buf;
-
int i;
-
int seconds;
-
-
srand(getpid());
-
-
p_buf.sem_num = CHILD_NR;
-
p_buf.sem_op = 1;
-
p_buf.sem_flg = 0;
-
-
my_buf.sem_num = num;
-
my_buf.sem_op = -1;
-
my_buf.sem_flg = 0;
-
for (i = 0; i < 5; i++) {
-
semop(semid, &my_buf, 1); /*等待父进程释放第m个信号量,获得信号量前处于阻塞状态*/
-
-
seconds = (unsigned)rand() % 4 + 1; /*模拟子进程的运行*/
-
sleep(seconds);
-
printf("%d ", num + 1);
-
fflush(NULL);
-
-
semop(semid, &p_buf, 1); /*释放第7个信号量,6个子进程退出后,父进程将获得第7个信号量的控制权*/
-
}
-
-
return;
-
}
-
int main(void)
-
{
-
pid_t pid;
-
int semid;
-
struct sembuf my_buf, child_buf[CHILD_NR];/*信号量操作由sembuf结构体数组决定*/
int i
;
-
unsigned short arr[CHILD_NR + 1] = { /*用于初始化信号量,信号量是一个整形数组*/
-
[CHILD_NR] = CHILD_NR,
-
};
-
-
semid = semget(IPC_PRIVATE, CHILD_NR + 1, IPC_CREAT | 0600);
-
/*创建信号量集*/
-
if (semid == -1) {
-
perror("semget()");
-
return 1;
-
}
-
-
semctl(semid, 0, SETALL, arr);
-
/*初始化信号量集*/
-
-
for (i = 0; i < CHILD_NR; i++) {
-
pid = fork(); /*创建CHILD_NR个子进程*/
-
/* if error */
-
if (pid == 0) {
-
child(semid, i);
-
return 0;
-
}
-
}
-
/*初始化信号操作结构体数组*/
-
for (i = 0; i < CHILD_NR; i++) {
-
child_buf[i].sem_num = i;
-
child_buf[i].sem_op = 1;
-
child_buf[i].sem_flg = 0;
-
}
-
my_buf.sem_num = CHILD_NR;
-
my_buf.sem_op = -CHILD_NR;
-
my_buf.sem_flg = 0;
-
-
#if 0
-
/* debug */
-
int val;
-
val = semctl(semid, CHILD_NR, GETVAL);
-
if (val == -1) {
-
perror("semctl(GETVAL)");
-
}
-
printf("debug: sem[%d] = %d\n", CHILD_NR,val);/*打印信号量的值j*/
-
#endif
-
for (i = 0; i < 5; i++) {
-
semop(semid, &my_buf, 1); /*获取第7个信号量控制的资源*/
-
printf("\n");
-
-
semop(semid, child_buf,CHILD_NR);/*释放第0-5个信号量控制的资源*/
-
}
-
semop(semid, &my_buf, 1);
-
/*等待子进程最后一次释放完资源后,再输出一次回车*/
-
printf("\n");
-
-
semctl(semid, 0, IPC_RMID); /*删除信号量集合*/
-
for (i = 0; i < CHILD_NR; i++) {
-
wait(NULL); /*收尸*/
-
}
-
-
return 0;
-
}
阅读(2542) | 评论(2) | 转发(1) |