我正在设计一个程序,该程序包含三个线程,分别模拟消费者/生产者的原则ControlEntrada
和ControlSalida
,其中两个初始化定时器,分别生成两个信号,并且无限长循环等待信号,捕获后,它必须发送到最后一个负责监视和捕获这些信号的线程,根据信号,它将执行一项或另一项任务,我认为我的主要目的是已完成,但我不知道每次计时器到期并且信号是在sigwait中捕获的,如何发送到Monitorizar
线程以进行捕获,任何想法?这是我的代码:
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define NUM_THREADS 3
#define SIG_1 SIGUSR1
#define SIG_2 SIGUSR2
pthread_t hebras[NUM_THREADS];
int aforo=0;
static void error(int errnum, const char* msg)
{
char buf[127];
const char* sep = (msg != NULL ? ": " : "");
msg = (msg != NULL ? msg : "");
strerror_r(errnum, buf, sizeof(buf));
fprintf(stderr, "%s%s%s\n", msg, sep, buf);
exit(EXIT_FAILURE);
}
void *ControlEntrada(void * arg){
printf("Creando la hebra entrada.\n");
//int signum;
sigset_t * set = (sigset_t *) arg;
timer_t timer;
struct itimerspec required;
//struct itimerspec old;
struct timespec first;
struct timespec period;
struct sigevent sig;
sig.sigev_notify = SIGEV_SIGNAL;
sig.sigev_signo = SIG_1;
sig.sigev_value.sival_ptr = &timer;
if(timer_create(CLOCK_MONOTONIC, &sig, &timer)!=0){
error(errno,"error_timer_create para entrada");
}
if(clock_gettime(CLOCK_MONOTONIC, &first)!=0){
error(errno,"error_clock_gettime para entrada");
}
first.tv_sec = 0;
period.tv_sec = 1;
required.it_value = first;
required.it_interval = period;
if(sigemptyset(set)!=0){
error(errno,"error_sigemptyset para entrada");
}
if(sigaddset(set, SIG_1)!=0){
error(errno,"error_sigaddset para entrada");
}
if(pthread_sigmask(SIG_BLOCK, set, NULL)!=0){
error(errno,"error_sigprocmask para entrada");
}
if(timer_settime(timer, 0, &required, NULL)!=0){
error(errno,"error_timer_settime para entrada");
}
printf("Creado timer para la entrada.\n");
while(1){
sigwait(set, &signum);
if(signum==SIG_1){
// How to send signal to 'Monitorizar' thread?
}
}
return 0;
}
void *ControlSalida(void * arg){
printf("Hebra salida.\n");
sigset_t * set = (sigset_t *) arg;
timer_t timer;
struct itimerspec required;
//struct itimerspec old;
struct timespec first, period;
struct sigevent sig;
//sigset_t set;
int signum;
sig.sigev_notify = SIGEV_SIGNAL;
sig.sigev_signo = SIG_2;
sig.sigev_value.sival_ptr = timer;
if(clock_gettime(CLOCK_MONOTONIC, &first)!=0){
error(errno,"error_clock_gettime para salida");
}
first.tv_sec = 0;
period.tv_sec = 2;
required.it_value = first;
required.it_interval = period;
if(timer_create(CLOCK_MONOTONIC, &sig, &timer)!=0){
error(errno,"error_timer_create para salida");
}
if(sigemptyset(set)!=0){
error(errno,"error_sigemptyset para salida");
}
if(sigaddset(set, SIG_2)!=0){
error(errno,"error_sigaddset para salida");
}
if(pthread_sigmask(SIG_BLOCK, set, NULL)!=0){
error(errno,"error_sigprocmask para salida");
}
if(timer_settime(timer, 0, &required, NULL)!=0){
error(errno,"error_timer_settime para salida");
}
printf("Creado timer para la salida.\n");
while(1){
sigwait(set, &signum);
if(signum==SIG_2){
// How to send to 'Monitorizar' thread?
}
}
return 0;
}
void * Monitorizar(void * arg){
printf("Entrando en monitorizar\n");
int sig, err;
sigset_t * set = (sigset_t *) arg;
while(1){
// espera la señal
err=sigwait(set, &sig);
if(err!=EINTR){
error(err,"error_sigwait");
}
else{
if(sig==SIG_1){
// incrementamos el aforo de entrada
aforo++;
printf("Entrando gente... Aforo: %d\n",aforo);
}
else if(sig==SIG_2){
// decrementamos el aforo de salida
aforo--;
printf("Saliendo gente... Aforo: %d\n",aforo);
}
}
}
}
int main(){
sigset_t set;
pthread_attr_t attr;
int err;
pthread_attr_init(&attr);
printf("Creando en main la 3º hebra.\n");
if((err=pthread_create(&hebras[2], &attr, Monitorizar, &set))!=0){
error(err, "pthread_create");
}
//pthread_join(hebras[2],NULL);
printf("Creando en main la 1º hebra.\n");
if((err=pthread_create(&hebras[0], &attr, ControlEntrada, &set))!=0){
error(err, "pthread_create");
}
printf("Creando en main la 2º hebra.\n");
/*if((err=pthread_create(&hebras[1], &attr, ControlSalida, &set))!=0){
error(err, "pthread_create");
}*/
//pthread_join(hebras[0],NULL);
//pthread_join(hebras[1],NULL);
//return 0;
pthread_exit(NULL);
}