如何在POSIX中将信号从一个线程传递到另一个线程

时间:2014-09-08 23:35:22

标签: c timer pthreads signals posix

我正在设计一个程序,该程序包含三个线程,分别模拟消费者/生产者的原则ControlEntradaControlSalida,其中两个初始化定时器,分别生成两个信号,并且无限长循环等待信号,捕获后,它必须发送到最后一个负责监视和捕获这些信号的线程,根据信号,它将执行一项或另一项任务,我认为我的主要目的是已完成,但我不知道每次计时器到期并且信号是在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);
    }

0 个答案:

没有答案