1

我正在用 c 语言开发一个实现信号量的多线程生产者-消费者程序。每个缓冲区结构都有两个通用信号量——一个用于空缓冲区,一个用于满缓冲区。但是,当程序进入 readInput 函数时,这两个信号量的值会变为随机值。线程结构内的信号量很好,但是线程结构内的 IO 联合内的缓冲区结构内的信号量由于某种原因发生了变化。知道为什么会这样吗?

#include "st.h"
#include "semaphore.h"
#include "buffer.h"

/*Definitions here*/
//Input location.
#define DEFAULT_IN stdin
//Output location.
#define DEFAULT_OUT stdout
//Line width
#define LINE_SIZE 80
#define SLEEP_TIME 333333

//Shorthand for structure components
#define INPUT thread->in
#define MUTEX thread->mutex
#define OUTPUT thread->out

/*Global variables here*/

//The input/output can be a stream or a buffer.
typedef union
{
    buffer *bufferIO;   //Buffer to read from/write to.
    FILE *stream;       //An I/O stream.
} IO;

//Each thread has an input, a semaphore, and an output.
typedef struct
{
        IO in;          //Either an input stream or a buffer to read.
        semaphore *mutex;   //Pointer to a binary semaphore.
        IO out;         //Either an output stream or a buffer to write.
} Thread;


/*Function prototypes here*/
void *readInput(void *s);
void *processLines(void *s);
void *processAsterisks(void *s);
void *writeOutput(void *s);

int main (int argc, char const *argv[])  //The main function  
{
    st_init();

    /*Binary semaphore*/
    semaphore mutex;        //Binary semaphore for mutual exclusion.
    createSem(&mutex, 1);

    printf("Beginning...\n");
    /*The three buffers between threads*/
    buffer B1, B2, B3;
    createBuf(&B1);
    createBuf(&B2);
    createBuf(&B3);

    /*The 5 data locations*/
    IO input, buffer1, buffer2, buffer3, output;    //stdin, 3 buffers, stdout

    /*Set the unions*/
    input.stream = DEFAULT_IN;  //Input stream
    buffer1.bufferIO = &B1;     //Contains raw input
    buffer2.bufferIO = &B2;     //Newlines have become spaces
    buffer3.bufferIO = &B3;     //** has become ^
    output.stream = DEFAULT_OUT;    //Output stream, 80 at a time

    /*Initialize the threads*/
        Thread input_thread = {input, &mutex, buffer1};         //Recieve input
        Thread proc1_thread = {buffer1, &mutex, buffer2};       //Returns to spaces
        Thread proc2_thread = {buffer2, &mutex, buffer3};       //** to ^
        Thread output_thread = {buffer3, &mutex, output};       //Output 80 characters and a newline.

    printf("%i\n", input_thread.out.bufferIO->emptyBuffers->value);
    /*Create the actual threads*/
    if(st_thread_create(readInput, &input_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for input thread failure");
        exit(1);
    }
    printf("%i\n", input_thread.out.bufferIO->emptyBuffers->value);
    if(st_thread_create(processLines, &proc1_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for line thread failure");
        exit(1);
    }
    if(st_thread_create(processAsterisks, &proc2_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for asterisk thread failure");
        exit(1);
    }
    if(st_thread_create(writeOutput, &output_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for output thread failure");
        exit(1);
    }

    st_thread_exit(NULL);
    return 0;
}
/*Function definitions here*/
void *readInput(void *s)
{
    Thread *thread = s;
    char c;                 //An individual character.

    printf("Type some input.\n");
    do
    {
        down(MUTEX);
        c = getc(INPUT.stream);     //Consume a character from input.
    printf("%i\n", OUTPUT.bufferIO->emptyBuffers->value);
        deposit(OUTPUT.bufferIO, c);    //Produce a character.
        up(MUTEX);
        st_usleep(SLEEP_TIME);      //Wait.
    }
    while(c != EOF);            //Do-while in order to pass on the EOF as an exit flag.

    //EOF reached - exit thread.
    //assert(c == EOF);

    printf("\nDone reading.");
    st_thread_exit(NULL);
}...

用gdb查看它后,我发现了这个:

Hardware watchpoint 10: (*(*input_thread.out.bufferIO).emptyBuffers).value
(gdb) c
Continuing.
Hardware watchpoint 10: (*(*input_thread.out.bufferIO).emptyBuffers).value

Old value = 80
New value = 4216725
0x000000395221467c in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2

不确定这个 _dl_runtime_resolve 是什么。

4

1 回答 1

0

semaphore and buffers are created as stack variables in main thread so when the main thread exits the address pointing to semaphore and buffer are invalid and the behavior is unpredictable. Make the proper design and give proper scope to the variables, for time being make all the variables as global. Make the following things in the above code as global

  1. semaphore mutex; //Binary semaphore for mutual exclusion.

    AND

  2. IO input, buffer1, buffer2, buffer3, output; //stdin, 3 buffers, stdout

recompile and execute

于 2012-10-08T10:24:58.533 回答