1

我正在使用 putty 运行以下代码,预期的行为应该如下:当负责读取文件的线程结束时,负责计时器的另一个线程也必须结束并反转:如果负责计时器已经结束,另一个也必须结束。但是我得到了这个致命的错误:Server unexpectedly closed network connection当还剩一分钟时。我做错了什么?

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

/* global variables to check the state*/
int read = 0;
int timeLeft = 0;

void *readFromFile(void *myFile)
{

  int state;
  char *theFile;
  theFile = (char*) myFile;
  char question[100];
  char answer[100];
  state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL );
  FILE *file = fopen(theFile, "r");
  if (file != NULL )
  {
    while (fgets(question, sizeof question, file) != NULL )
    {
      fputs(question, stdout);
      scanf("%s", &answer);
    }
    fclose(file);
    state = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL );
    printf("Done with questions!\n");
    read = 1;

  }
  else
  {
    perror(theFile);
  }
}

void displayTimeLeft(void *arg)
{
  int *time;
  int state;
  time = (int*) arg;
  int i;
  state = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL );
  for (i = time; i >= 0; i -= 60)
  {
    if (i / 60 != 0)
    {
      printf("You have %d %s left.\n", i / 60,
          (i / 60 > 1) ? "minutes" : "minute");
      sleep(60);
    }
    else
    {
      state = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL );
      printf("The time is over \n");
      timeLeft = 1;
      break;
    }
  }
}

int main()
{
  pthread_t thread1;
  pthread_t thread2;
  char *file = "/home/osystems01/laura/test";
  int *time = 180;

  int ret1;
  int ret2;
  ret1 = pthread_create(&thread1, NULL, readFromFile, file);
  ret2 = pthread_create(&thread2, NULL, displayTimeLeft, time);

  printf("Main function after pthread_create\n");

  while (1)
  {
    if (read == 1)
    {

      pthread_cancel(thread2);
      pthread_cancel(thread1);
      break;
    }
    else if (timeLeft == 1)
    {

      pthread_cancel(thread1);
      pthread_cancel(thread2);
      break;
    }

  }

  printf("After the while loop!\n");

  return 0;
}
4

2 回答 2

0

正如我在评论中提到的,我强烈怀疑服务器是否会关闭通过 putty 建立的连接,因为您的程序存在问题。

但是,程序代码存在几个问题。


ost 关键问题是您正在从两个线程同时访问两个全局变量。

需要保护并发访问。为此,声明两个互斥锁,如下所示:

pthread_mutex_t mutex_read = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_time = PTHREAD_MUTEX_INITIALIZER;


void *readFromFile(void *myFile)
{
    ...

    {
      int result = pthread_mutex_lock(mutex_read);
      if (0 != result)
      {
        perror("pthread_mutex_lock(mutex_read) failed");
      }
    }

    read = 1;

    {
      int result = pthread_mutex_unlock(mutex_read);
      if (0 != result)
      {
        perror("pthread_mutex_unlock(mutex_read) failed");
      }
    }

    ...
}


void displayTimeLeft(void *arg)
{
    ...

    {
      int result = pthread_mutex_lock(mutex_time);
      if (0 != result)
      {
        perror("pthread_mutex_lock(mutex_time) failed");
      }
    }

    timeLeft= 1;

    {
      int result = pthread_mutex_unlock(mutex_time);
      if (0 != result)
      {
        perror("pthread_mutex_unlock(mutex_time) failed");
      }
    }

    ...

}

int main(void)
{
  ...

  while(1)
  {
    int bread = 0;
    int btimeLeft = 0;

    {
      int result = pthread_mutex_lock(mutex_read);
      if (0 != result)
      {
        perror("pthread_mutex_lock() failed");
      }
    }

    bread = (1 == read);

    {
      int result = pthread_mutex_unlock(mutex_read);
      if (0 != result)
      {
        perror("pthread_mutex_unlock() failed");
      }
    }

    {
      int result = pthread_mutex_lock(mutex_time);
      if (0 != result)
      {
        perror("pthread_mutex_lock() failed");
      }
    }

    btimeLeft = (1 == timeLEft);

    {
      int result = pthread_mutex_unlock(mutex_time);
      if (0 != result)
      {
        perror("pthread_mutex_unlock() failed");
      }
    }

    if (bread == 1)
    {

      pthread_cancel(thread2);
      pthread_cancel(thread1);
      break;
    }
    else if (btimeLeft == 1)
    {

      pthread_cancel(thread1);
      pthread_cancel(thread2);
      break;
    }
  }  
  ...

对于 PThreads thr threas 函数需要声明为:

void * (*) (void *)

情况并非如此displayTimeLeft


在“字符串”中扫描时,需要传递表示字符串的字符数组的第一个元素的地址。所以这

scanf("%s", &answer);

应该是这个

scanf("%s", &answer[0]);

或这个

scanf("%s", answer);

代码错过了 的原型sleep(),所以添加

#include <unistd.h>

完成此操作后,编译器会检测到系统调用与代码声明read()的全局变量之间的名称冲突。read这不好。重命名readreadit.


最后同样重要的是,嫌疑人他的回答中提到了这个问题。您正在滥用指向 an 的指针来int存储一些时间值 ( int * time = 180)。不要那样做。

要解决此问题,请这样做:

int main(void)
{
  ...
  int time = 180;
  ...
  ret2 = pthread_create(&thread2, NULL, displayTimeLeft, &time);

并在displayTimeLeft做:

 int time = *((int*) arg);
于 2013-11-10T14:42:20.293 回答
0

在这里,您正在初始化一个指向内存位置 180 的指针。

int *time = 180;

需要的是:

int time = 180;
...
...
ret2 = pthread_create(&thread2, NULL, displayTimeLeft, &time);
于 2013-11-10T13:01:16.820 回答