当不需要使用有名信号量关联的名字时,可改用基于内存的信号量。基于内存的信号量至少具有随进程的持续性,然而他们真正的持续性却取决于存放信号量的内存区的类型。只要含有某个基于内存信号量的内存区保持有效,该信号量就一直存在。
1.如果某个基于内存的信号量是由单个进程内的各个线程共享的(sem_init函数的入参shared为0),那么该信号量具有随进程的持续性,当该进程终止时它也就消失了。
2.如果某个基于内存的信号量是在不同进程间共享的
(sem_init函数的入参shared为1),那么该信号量必须存放在共享内存中,因而只要共享内存区仍然存在,该信号量就一直存在。POSIX共享内存区和system V共享内存区都具有随内核的持续性。这意味着服务器可以创建一个共享内存区,在该共享内存区中初始化一个Posix基于内存的信号量,然后终止。一段时间后,一个或多个客户可打开该共享内存区,访问该信号量。
sem_t mysem;
sem_init(&mysem,1,0);
if(fork() == 0) {
......
sem_post(&mysem);
}
sem_wait(&mysem);
以上例子中虽然sem_init函数的shared置为1,表示进程间的内存信号量,但是由于mysem信号量并不存在于共享内存中,所以这个例子中的信号量实际是不能在父子进程间使用的。fork出来的子进程通常不共享父进程的内存空间。子进程是在父进程内存空间的副本上启动的,它跟共享内存区不是一回事。
posix内存信号量的生产者和消费者例子:
-
#include "../unipc.h"
-
-
#define NBUFF 10
-
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
-
int nitems;
-
-
struct {
-
int buff[NBUFF];
-
sem_t mutex,nempty,nstored;
-
} shared;
-
-
void *produce(void *arg)
-
{
-
int i;
-
for(i = 0;i < nitems; i++) {
-
sem_wait(&shared.nempty);
-
sem_wait(&shared.mutex);
-
shared.buff[i%NBUFF] = i;
-
sem_post(&shared.mutex);
-
sem_post(&shared.nstored);
-
}
-
return NULL;
-
}
-
-
void *consume(void *arg)
-
{
-
int i;
-
for(i = 0;i < nitems; i++) {
-
sem_wait(&shared.nstored);
-
sem_wait(&shared.mutex);
-
if(i != shared.buff[i%NBUFF]) {
-
printf("i = %d,buff[%d]=%d\n",i,i,shared.buff[i]);
-
}
-
sem_post(&shared.mutex);
-
sem_post(&shared.nempty);
-
}
-
return NULL;
-
}
-
-
int main(int argc ,char *argv[])
-
{
-
int nitems;
-
pthread_t ptid_produce,ptid_consume;
-
-
if(argc != 2 ) {
-
printf("usage produce1 <#items>\n");
-
return -1;
-
}
-
nitems = atoi(argv[1]);
-
-
sem_init(&shared.mutex,0,1);
-
sem_init(&shared.nempty,0,NBUFF);
-
sem_init(&shared.nstored,0,0);
-
-
pthread_create(&ptid_produce,NULL,produce,NULL);
-
pthread_create(&ptid_consume,NULL,consume,NULL);
-
-
pthread_join(ptid_produce,NULL);
-
pthread_join(ptid_consume,NULL);
-
-
sem_destroy(&shared.mutex);
-
sem_destroy(&shared.nempty);
-
sem_destroy(&shared.nstored);
-
return 0;
-
}
阅读(1166) | 评论(0) | 转发(0) |