2015-11-04 6 views
2
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <semaphore.h> 

pthread_mutex_t mutex_lock; 

/* semaphore declarations */ 
sem_t students_sem; /* ta waits for a student to show up, student notifies ta his/her arrival */ 
sem_t ta_sem;  /* students waits for ta to help, ta notifies student he/she is ready to help */ 

/* the number of waiting students */ 
int waiting_students; 

/* ta sleeping status indicator */ 
int ta_sleep = 1; 
/* the maximum time (in seconds) to sleep */ 
#define MAX_SLEEP_TIME 3 

/* number of potential students */ 
#define NUM_OF_STUDENTS 4 

#define NUM_OF_HELPS 2 

/* number of available seats */ 
#define NUM_OF_SEATS 2 

/* Student IDs */ 
int stud_id[NUM_OF_STUDENTS]; 

/* TA and student threads */ 
pthread_t students_thread[NUM_OF_STUDENTS]; 
pthread_t ta_thread; 

/* function prototype */ 
void* ta_check(void* p); 
void* student_check(void* p); 

int main (void) 
{ 
    /* local variable declaration */ 
    int i; 

    /* initialize mutex and semaphore */ 
    pthread_mutex_init(&mutex_lock, NULL); 
    sem_init(&ta_sem, 0, 0); 
    sem_init(&students_sem,0,0); 

    /* create ta thread */ 
    pthread_create(&ta_thread, 0, ta_check,0); 

    /* create student threads */ 
    for (i = 0; i < NUM_OF_STUDENTS; i++) 
     pthread_create(&students_thread[i], 0, student_check,(void*)&stud_id[i]); 

    /* join student threads */ 
    for (i = 0; i < NUM_OF_STUDENTS; i++) 
     pthread_join(students_thread[i], NULL); 

    /* cancel ta thread when all student threads terminate */ 
    pthread_cancel(ta_thread); 
    printf("The TA finished helping all students.\n"); 

    return 0; 
} 

void* ta_check(void* p) 
{ 
    /* invoke random number generator */ 
    rand_r(time(NULL)); 
    while (1) 
    { 
     pthread_mutex_lock(&mutex_lock); 
     ta_sleep = 1; 
     pthread_mutex_unlock(&mutex_lock); 
     sem_wait(&students_sem); 
     // help a student 
     printf("Helping a student for %d seconds, # of waiting students = %d", MAX_SLEEP_TIME, waiting_students); 
     sleep(MAX_SLEEP_TIME); 
     // check if there are more student to help 
     while (waiting_students > 0) 
     { 
      sem_post(&ta_sem); 
      pthread_mutex_lock(&mutex_lock); 
      waiting_students--; 
      pthread_mutex_unlock(&mutex_lock); 
      // help student 
      printf("Helping a student for %d seconds, # of waiting students = %d", MAX_SLEEP_TIME, waiting_students); 
      sleep(MAX_SLEEP_TIME); 
     } 
    } 
    return NULL; 
} 

void* student_check(void* p) 
{ 
    /* invoke random number generator */ 
    rand_r((unsigned*)1); 
    int num_help = 0; 
    int seat_taken = 0; 

    while (num_help <= NUM_OF_HELPS) 
    { 
     // check if ta is not sleeping 
     if (!ta_sleep) 
     { 
      if (!seat_taken) 
      { 
       if (waiting_students < NUM_OF_SEATS) 
       { 
        // student take a seat 
        seat_taken = 1; 
        pthread_mutex_lock(&mutex_lock); 
        waiting_students++; 
        pthread_mutex_unlock(&mutex_lock); 
        printf("Stdudent %d takes a seat, # of waiting student = %d", *(int*)p, waiting_students); 
        sem_wait(&ta_sem); 
        seat_taken = 0; 
        num_help++; 
       } 
       else 
       { 
        printf("\tStudent %d programming for %d seconds\n",*(int*)p,MAX_SLEEP_TIME); 
        sleep(MAX_SLEEP_TIME); 
        printf("\tStudent %d will try later\n",*(int*)p); 
       } 
      } 
     } 
     // check if ta is sleeping 
     else if (ta_sleep) 
     { 
      pthread_mutex_lock(&mutex_lock); 
      ta_sleep = 0; 
      pthread_mutex_unlock(&mutex_lock); 
      sem_post(&students_sem); 
      sem_wait(&ta_sem); 
      num_help++; 
     } 
    } 
    printf("Student %d is receiving help", *(int*)p); 
    return NULL; 
} 

После того, как я закончил исправление всех сообщений об ошибках и предупреждениях для этой программы, я впервые встретил это сообщение об ошибке segmentation fault(core dumped). Он никогда не появлялся до того, как я отлаживал эту программу. Могу ли я получить некоторую помощь в поиске, где произошла эта ошибка. Большое вам спасибо за помощь.сообщение об ошибке сегментации (core dumped)

+1

Что говорит gdb? –

+1

Я бы рекомендовал использовать отладчик типа gdb, см. [Здесь] (http://www.unknownroad.com/rtfm/gdbtut/gdbsegfault.html) – plonser

+0

Спасибо, я запустил gdb, и он сказал, что ошибка произошла в функции rand_r, но теперь мне трудно понять, почему эта функция вызывает проблемы. – KhoaVo

ответ

3

rand_r функция нуждается указатель без знака Int (не то же использования, чем rand

Таким образом, вы должны делать:

unsigned int myrand = (unsigned int)time(NULL); 
rand_r(&myrand); 
0

Когда я запускаю его в gdb, я вижу жалобу rand_r():.

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7ffff77f6700 (LWP 6018)] 
rand_r (seed=0x5639d757) at rand_r.c:31 
31 rand_r.c: No such file or directory. 
(gdb) bt 
#0 rand_r (seed=0x5639d757) at rand_r.c:31 
#1 0x0000000000400af7 in ta_check (p=0x0) at foo.c:71 
#2 0x00007ffff7bc4182 in start_thread (arg=0x7ffff77f6700) at pthread_create.c:312 
#3 0x00007ffff78f147d in clone() at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111 
+0

thank, я получил тот же журнал ошибок, когда я запускал gdb, но теперь я не знаю, почему произошла ошибка в rand_r() – KhoaVo

0

Это ваша проблема: rand_r ((без знака *) 1) (Также rand_r (время (NULL))

Каждый раз, когда вы обнаруживаете, что листинг буквального указателя (и вы не выполняете глубоко встроенное программирование), вы должны быть подозрительными (и когда вы пишете драйверы, вы должны быть параноидальными).

В этом случае rand_r ЗАПИСИТ в память, указанную указателем, поэтому это должно быть для потока int, а не для литерала.

rand_r (время (NULL) не будет segfault, но также не будет работать так, как вы ожидаете, потому что вы в действительности повторно заправляете RNG с текущим временем каждый раз, когда вы вызываете вещь (я ожидаю, что выход RNG изменится ровно один раз второй - в этом случае).

Простейшая вещь может заключаться в том, чтобы сделать небольшие структуры студентов и ТП и содержать каждый элемент int rand_state, который вы можете инициализировать со случайными значениями перед началом потоков (исходные семена), а затем вызов rand_r (& student-> rand_state) даст вам ожидаемый результат. Эти структуры могут также содержать pthread для учащегося или TA.

С уважением, Дэн.

+0

Спасибо, Я исправить это, используя unsigned int seed – KhoaVo

Смежные вопросы