繁体   English   中英

Pthread 生产者/消费者作业问题。 你能告诉我为什么我的程序没有将文件中的所有单词都写入 output 吗?

[英]Pthread producer/consumer homework problem. Can you tell me why my program isn't writing all the words from the file to output?

我必须为我的操作系统 class 编写一个 C 程序。 这是 Linux 的生产者/消费者问题。 问题描述说明主线代码为输入文件打开一个文件描述符,并创建了三个pthreads。 每个pthread是要执行不同的function。

文件描述符被传递给第一个 pthread,它从输入文件中逐行读取行到与第二个 pthread 共享的缓冲区中。 缓冲区大小为 10。

第二个 pthread 从共享缓冲区中读取行,并将每行拆分为一组单词。 然后将每个字读入与第三个 pthread 共享的第二个缓冲区。 第二个缓冲区大小为 20。

第三个 pthread 从第二个缓冲区读取字,计算读取的字数,并将每个字写入标准 output。

由于某种原因,我的算法无法将文件中的所有单词写入标准 output。 有时我会遇到分段错误,有时它只将一些单词打印到 output 然后退出,有时程序会挂起。 我无法弄清楚问题出在哪里。

我的代码:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

// first shared buffer
char line_buffer[10][200];
int in1 = 0;
int out1 = 0;

// second shared buffer
char word_buffer[20][50];
int in2 = 0;
int out2 = 0;


// function for first pthread
void * one(void *arg) {
  int file = *((int *)arg);
  char next_char_buffer[1];
  int n;
  int i;

  while ((n=read(file, next_char_buffer,1)) > 0) {
    while ((in1 + 1) % 10 == out1) {
      // first buffer full
      sched_yield();
    }
    
    if (next_char_buffer[0] == '\n') { // end of line
      line_buffer[in1][i] = '\0'; // null terminate string
      in1 = ++in1 % 10;
      i = 0;
    }
    else {
      // read char to buffer      
      line_buffer[in1][i++] = next_char_buffer[0];
    }
  }

  while ((in1 + 1) % 10 == out1) {
    // first buffer full    
    sched_yield();
  }
  line_buffer[in1][0] = '\0'; // EOF signal for second thread
  in1 = ++in1 % 10;

  printf("Exit 1 \n");
  pthread_exit(NULL);
}


// function for second pthread
void * two(void *arg) {
  int i;
  
  // left and right indexes of a word in the line
  int l;
  int r;

  int lines = 0; // number of lines read

  while (lines == 0 || line_buffer[out1][0] != '\0') {
    while (in1 == out1) {
      // first buffer empty      
      sched_yield();
    }

    l = 0;
    r = 0;

    while (line_buffer[out1][r] != '\0') {
      if (line_buffer[out1][r] == ' ') {
        while ((in2 + 1) % 20 == out2) {
          // second buffer full
          sched_yield();
        }
        while (l < r) {
          // write char to second buffer
          word_buffer[in2][i++] = line_buffer[out1][l++];
        }
        word_buffer[in2][i] = '\0'; // null terminate string
        in2 = ++in2 % 20;
        i = 0;
        l++;
        r++;
      }
      else {
        r++;
      }
    }
    out1 = ++out1 % 10;
    lines++;  
  }
  
  while ((in2 + 1) % 20 == out2) {
    // second buffer full
    sched_yield();
  }
  word_buffer[in2][0] = '\0'; // signal end of input
  in2 = ++in2 % 20;

  printf("Exit 2\n");
  pthread_exit(NULL);
}



// function for third pthread
void * three(void *arg) {
  int i = 0;
  int words = 0; // word count
  
  while(words == 0 || word_buffer[out2][0] != '\0') {
    while (in2 == out2) {
      // second buffer empty
      sched_yield();
    }
    printf("%s \n\n", word_buffer[out2]);
    words++;
    out2 = ++out2 % 20;
    i++;
  }
  printf("Word count: %d \n",words);
  printf("Exit 3\n");
  pthread_exit(NULL);
}







int main(int argc, char *argv[]) {
  // Check for 2 arguments or raise error
  if (argc != 2){
    write(STDERR_FILENO,"Error 1\n",8);
    exit(-1);
    return -1;
  }

  // file descriptor
  int file;
  if ((file = open(argv[1], O_RDONLY, 0)) == -1) {
    printf("Can't open file");
    exit(-1);
    return -1;
  }

  // create pthreads
  pthread_t tid_1, tid_2, tid_3;
  pthread_create(&tid_1, NULL, one, &file);
  pthread_create(&tid_2, NULL, two, NULL);
  pthread_create(&tid_3, NULL, three, NULL);

  // join pthreads
  pthread_join(tid_1,NULL);
  pthread_join(tid_2,NULL);
  pthread_join(tid_3,NULL);  


  // close the file
  printf("Exit main");
  exit(0);
  return 0;
}

您的程序在没有任何同步的情况下从多个线程访问变量(例如in1in2等)。

这是一场数据竞赛,它是未定义的行为,并使您的程序的结果未定义——它可以做任何事情。

下一个错误是one()two()中的i可能未初始化使用——最好在声明变量时初始化它们。

下一个错误是two()仅在找到空格时才发出单词,因此每行都吃掉最后一个单词。

修复了上述错误后,程序可以工作,但仍会出现数据竞争。 您需要使用_Atomic类型来避免这种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM