2011-09-17 6 views
-1

누군가 내 코드를 확인하고 내가 올바른 길을 가고 있는지 말해 줄 수 있나? 내가 조금은 잃어버린 것처럼 보인다. 내 실수를 본다면, 내게 그걸 알려줘 ..한정된 버퍼를 가진 프로듀서/소비자

내가하려는 것은 GCD뿐 아니라 내 자신의 세마포어를 사용하여 바운드 버퍼를 해결하는 것입니다. 사전에

감사합니다 ..

sema.c

void procure(Semaphore *semaphore) { 

     pthread_mutex_lock(semaphore->mutex1); 

     while(semaphore->value <= 0) 
       pthread_cond_wait(&semaphore->condition, semaphore->mutex1); 


     semaphore->value--; 

     pthread_mutex_unlock(semaphore->mutex1); 


} 

void vacate(Semaphore *semaphore) { 

     pthread_mutex_lock(semaphore->mutex1); 
     semaphore->value++; 
     pthread_cond_signal(&semaphore->condition); 
     pthread_mutex_unlock(semaphore->mutex1);   
} 


void init (Semaphore *semaphore){ 

     semaphore->value = 1; 

     pthread_mutex_t myMutex; 
     semaphore->mutex1 = &myMutex; 
     pthread_mutex_init(semaphore->mutex1, NULL); 



} 

void destroy (Semaphore *semaphore) { 

     pthread_mutex_destroy(semaphore->mutex1); 


} 

과 당신의 코드는 버그가

struct variables { 

     Semaphore *sem; 

}; 

struct variables vars; 

void constructer (int *buffer, int *in, int *out) { 

     init(vars.sem); 

} 


void deconstructer() { 

     destroy(vars.sem); 

} 



int rand_num_gen() { 
     uint_fast16_t buffer; 
     int file; 
     int *rand; 

     file = open("/dev/random", O_RDONLY); 


     while(1) { 

       read(file, &buffer, sizeof(buffer)); 

       printf("16 bit number: %hu\n", buffer); 

       *rand = (int) buffer; 

       close(file); 


       break; 
     } 

     return *rand; 
} 


void put_buffer(int* buffer, int* in, int* out) { 

     buffer[*in] = rand_num_gen(); // produce 

     procure(vars.sem);    // wait here 
       *in = (*in + 1) % BUF_SIZE; 
     vacate(vars.sem); 

} 

void get_buffer(int* buffer, int* in, int* out) { 

     int value; 

     procure(vars.sem); 
       value = buffer[*out]; 
     vacate(vars.sem); 

     *out = (*out + 1) % BUF_SIZE; 

} 

int main (void) { 


     int *in, *out, *buffer;  

     constructer(buffer, in, out);   



     dispatch_queue_t producer, consumer;  

     producer = dispatch_queue_create("put_buffer", NULL); 
     consumer = dispatch_queue_create("get_buffer", NULL); 



     dispatch_async(producer, 
         ^{ 
           int i; 
           do 
           { 
             put_buffer(buffer, in, out); 


             dispatch_async(consumer, 
                 ^{ 
                   get_buffer(buffer, in, out); 

                   if (i == RUN_LENGTH) exit(EXIT_SUCCESS); 
                 }); 
           } 
           while (i < RUN_LENGTH);    
         }); 

     dispatch_main();     

     deconstructer(); 

     exit (0); 
} 
+0

여기에 잘못된 액세스가 발생합니다. 'buffer [* in] = rand_num_gen(); 어떻게 해결할 수 있습니까? – canaan

+1

그 언어는 무엇입니까? C에는 람다 ('^') 연산자가 없습니다. –

답변

2

을 main.c. init 함수에서 로컬 변수의 주소를 semaphore->mutex1에 할당하고 함수가이 주소를 반환하면이 주소가 유효하지 않습니다. 나중에이 주소를 계속 사용하므로 정의되지 않은 동작으로 연결됩니다.

포인터가없는 세마포어에 직접 뮤텍스에 대한 메모리를 할당하거나 malloc을 통해 메모리를 할당해야합니다.

업데이트 :

프로그램이 당신은 확실히, 사용을 할당하고 버퍼를 참조하는 방법, 적절한 오류 처리를 할 메모리 관리에 대한 기본 개념을 배울 쉬운 주제를 선택해야 많은 버그를 가지고, 다음은 코드를 약간 수정 한 버전입니다. 여전히 효과가 없지만 따라야 할 아이디어가있을 것입니다.

#include <limits.h> 
#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 

void procure(Semaphore *semaphore) { 
    pthread_mutex_lock(semaphore->mutex1); 

    while (semaphore->value <= 0) 
    pthread_cond_wait(&semaphore->condition, semaphore->mutex1); 

    semaphore->value--; 
    pthread_mutex_unlock(semaphore->mutex1); 
} 

void vacate(Semaphore *semaphore) { 
    pthread_mutex_lock(semaphore->mutex1); 
    semaphore->value++; 
    pthread_cond_signal(&semaphore->condition); 
    pthread_mutex_unlock(semaphore->mutex1); 
} 

struct variables { 
    mutex_t sem_mutex; 
    Semaphore sem; 
}; 

struct variables vars; 

void constructor(int *buffer, int *in, int *out) { 
    vars.sem.value = 1; 
    vars.sem.mutex1 = &vars.sem_mutex; 
    pthread_mutex_init(vars.sem.mutex1, NULL); 
} 

void deconstructor() { 
    pthread_mutex_destroy(&semaphore->mutex1); 
} 

int rand_num_gen() { 
    const char *randomfile = "/dev/random"; 
    unsigned char buffer[2]; // Changed: always treat files as byte sequences. 
    FILE *f = fopen(randomfile, "rb"); 
    // Changed: using stdio instead of raw POSIX file access, 
    // since the API is much simpler; you don't have to care 
    // about interrupting signals or partial reads. 

    if (f == NULL) { // Added: error handling 
    fprintf(stderr, "E: cannot open %s\n", randomfile); 
    exit(EXIT_FAILURE); 
    } 
    if (fread(buffer, 1, 2, f) != 2) { // Added: error handling 
    fprintf(stderr, "E: cannot read from %s\n", randomfile); 
    exit(EXIT_FAILURE); 
    } 
    fclose(f); 
    int number = (buffer[0] << CHAR_BIT) | buffer[1]; 
    // Changed: be independent of the endianness of the system. 
    // This doesn't matter for random number generators but is 
    // still an important coding style. 
    printf("DEBUG: random number: %x\n", (unsigned int) number); 
    return number; 
} 

void put_buffer(int* buffer, int* in, int* out) { 
    buffer[*in] = rand_num_gen(); // produce 
    procure(&vars.sem); // wait here 
    *in = (*in + 1) % BUF_SIZE; 
    vacate(&vars.sem); 
} 

void get_buffer(int* buffer, int* in, int* out) { 
    int value; 
    procure(&vars.sem); 
    value = buffer[*out]; 
    vacate(&vars.sem); 
    *out = (*out + 1) % BUF_SIZE; 
} 

int main (void) { 
    int inindex = 0, outindex = 0; 
    int buffer[BUF_SIZE]; 

    constructor(buffer, &inindex, &outindex); 
    // Changed: provided an actual buffer and actual variables 
    // for the indices into the buffer. 
    dispatch_queue_t producer, consumer;  
    producer = dispatch_queue_create("put_buffer", NULL); 
    consumer = dispatch_queue_create("get_buffer", NULL); 

    dispatch_async(producer, ^{ 
    int i; 
    do { 
     put_buffer(buffer, &inindex, &outindex); 
     dispatch_async(consumer, ^{ 
     get_buffer(buffer, &inindex, &outindex); 
     if (i == RUN_LENGTH) exit(EXIT_SUCCESS); 
     }); 
    } while (i < RUN_LENGTH); 
    }); 

    dispatch_main();  
    deconstructor(); 
    exit (0); 
} 

내가 말했던 것처럼, 나는 모든 버그를 잡지 않았다.

+0

많은 버그가 있습니다. 하나를 가리켜 주셔서 감사합니다 ... – canaan

+0

나는 생성자와 해독 함수를 호출하지 않았습니다 .. 수정했지만 어떤 차이도 볼 수 없었습니다. – canaan

+0

'in' 변수를 초기화하지 않았습니다. 나는 당신이 in과 out 모두를 int = 0, out = 0으로 선언하고자한다고 생각한다. 당신의 기능에 그들의 주소를 전달하십시오. – nos

관련 문제