【发布时间】:2020-05-30 03:29:38
【问题描述】:
我正在尝试重新创建一个“黑盒”库。在我的 CS 课上,当我们应该使用信号量时(在我们的纸上决赛中),我们得到了一个“sem.h”文件。有 3 个函数,一个用于创建具有初始令牌数量的新信号量,一个用于从信号量中取出令牌,另一个用于将令牌放入信号量中。在 0 时,任何使用阻塞函数的线程都必须等待一个令牌。
为了更好地理解,我一直在尝试根据一些要求实现单一功能的考试重新创建这个 sem.h 和 sem.c。因为这一切都是为了在纸上完成,所以它不会编译,但我觉得很接近
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){
static 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;
}
如果不清楚这是做什么用的: 这些函数应该限制有多少线程可以同时访问一段代码 例子
//global
static SEM *sem = semCreate(1);
/.../
//critical segment in threadfunction
P(sem);
doReadAndWriteGlobalList();
V(sem);
一旦第一个线程通过 P(),任何后续的 P 调用都无法通过它,直到 V 在同一个 sem 上被调用
编译时出现以下错误:
sem.c: In function ‘semCreate’:
sem.c:14:3: error: field name not in record or union initializer
.val=initVal
^
sem.c:14:3: note: (near initialization for ‘sem’)
sem.c:14:8: error: initialization makes pointer from integer without a cast [-Werror=int-conversion]
.val=initVal
^~~~~~~
sem.c:14:8: note: (near initialization for ‘sem’)
sem.c:14:8: error: initializer element is not constant
sem.c:14:8: note: (near initialization for ‘sem’)
cc1: all warnings being treated as errors
【问题讨论】:
-
FWIW: (1)
semCreate()返回 NULL 表示失败,但你没有整理:如果pthread_mutex_init()失败,你应该free()SEM对象malloc()ed(假设你有);如果pthread_cond_init()失败,您应该pthread_mutex_destroy(),为了完整性,然后free();并且您需要延迟设置errno直到您真正返回。 (2)P()没有错误返回,所以调用者无法知道它失败了;errno也设置得太早了。 (3)V()同样,并且它可以返回仍然持有互斥锁!错误处理是 hard :-( -
请不要从问题中删除问题。如果您想回答自己的问题,请将其作为答案发布。
标签: c struct pthreads semaphore