我正在尝试重新创建“ Blackbox”库。在我的CS类中,当我们应该使用信号量时(在纸上最终版本中),我们得到了一个“ sem.h”文件。有3个函数,一个用于创建带有初始令牌数量的新信号量,一个用于从信号量中取出令牌,另一个用于将令牌放入信号量中的功能。为0时,使用阻塞功能的任何线程都必须等待令牌。
为了更好地理解,我一直在尝试根据要求执行单个功能的某些考试来尝试重新创建此sem.h和sem.c。由于所有这些操作都打算在纸上完成,因此不会编译,但我觉得我非常接近UPDATE它现在可以编译,我更新了代码,但是我还没有时间测试功能,我还没有实现Corret错误处理,正如另一位评论者指出的那样。我希望我会尽快对其进行测试,随着我的病情不断更新sem.h
typedef struct SEM SEM;
struct SEM *semCreate(int);
void P(struct SEM*); //tokens--
void V(struct SEM*); //tokens++
sem.c
#include "sem.h"
#include <pthread.h>
#include <errno.h>
typedef struct SEM{
volatile int val; //number of tokens
pthread_mutex_t m;
pthread_cond_t c;
}SEM;
/*create new semaphore with #initVal tokens */
SEM *semCreate(int initVal){
SEM *sem = malloc(sizeof(SEM));
sem->val=initVal;
errno = 0;
if((errno = pthread_mutex_init(&sem->m,NULL))!=0){
return NULL;
}
if((errno = pthread_cond_init(&sem->c,NULL))!=0){
return NULL;
}
return sem;
}
//take a token from the semaphore
void P(SEM *sem){
if((errno = pthread_mutex_lock(&sem->m))!=0){
return;
}
while(sem->val <=0){
if((errno=pthread_cond_wait(&sem->c,&sem->m))!=0){
pthread_mutex_unlock(&sem->m);
return;
}
sem->val--;
if(errno = pthread_mutex_unlock(&sem->m)!=0)return;
}
}
//put a token into the semaphore
void V(SEM *sem){
if((errno = pthread_mutex_lock(&sem->m))!=0){
return;
}
sem-> val++;
if((errno = pthread_cond_broadcast(&sem->c))!=0)return;
if((errno=pthread_mutex_unlock(&sem->m)!=0)) return;
}
//destroy a semaphore
void semDestroy(SEM* sem){
free(sem);
}
如果不清楚这是为了什么:函数应限制有多少线程可以同时访问一段代码例子
//global
static SEM *sem = semCreate(1);
/.../
//critical segment in threadfunction
P(sem);
doReadAndWriteGlobalList();
V(sem);
第一个线程通过P()后,对P的任何后续调用都将无法传递它,直到在同一时间调用V为止
edit现在,只要有时间测试不正确的代码,我就摆脱了编译器错误
您不需要静态变量。您想在每次调用semCreate
时创建一个新对象(内存分配)。因此,
static SEM *sem ={
.val=initVal
};
应该是
SEM *sem = malloc(sizeof(SEM));
sem->val = initVal;
完成操作后,别忘了释放信号量。
(可能还有其他问题。我只是在回答一个被问到的问题。)