【问题标题】:Multi thread reading from files多线程读取文件
【发布时间】:2018-11-18 23:30:05
【问题描述】:

我目前正在尝试使用三个单独的程序(process1、2 和 3)和一个我想从文件中读取并附加到字符串的主程序来生成输出。目前在我的函数中,我所做的只是 1. 打开文件,2. 读取字符,3. 将其附加到我的字符缓冲区,以及 4. 打印输出。 (这三个进程产生整数和字符的时间间隔不同)。

//Function for process 1 (Every second)
void thread1_func(void) {
  char *c; //Have to use *c because second param of strcat is a char pointer
  while(1) {
    usleep(50000);
    //Reading from file
    output = fopen("output1.txt", "r");
    fscanf(output, "%c", &c); //Copy int to c
    strcat(o1_buff, &c); //strcat it to char buffer
    printf("Thread 1 file input: %s\n", o1_buff);
    fclose(output);
  }
}

//Function for process 2 (Every 30 seconds)
void thread2_func(void) {
  char *number;
  while(1) {
    usleep(50000);
    //Reading from file
    output = fopen("output2.txt", "r");
    fscanf(output, "%c", &number);
    strcat(o2_buff, &number);
    printf("Thread 2 file input: %s\n", o2_buff);
    fclose(output);
  }
}

//Function for process 3 (Every 120 seconds)
void thread3_func(void) {
  char *character;
  while(1) {
    usleep(50000);
    //Reading from file
    output = fopen("output3.txt", "r");
    fscanf(output, "%c", &character);
    strcpy(o3_buff, &character);
    printf("Thread 3 file input: %s\n", o3_buff);
    fclose(output);
  }
 }

但是,在运行我的程序时,我收到以下错误消息

这到底是什么问题?如果问题是我的缓冲区已满(我由“char o1_buff[1024] = {'\0'}”等创建),那么我有一个单独的函数,我计划一次实现互斥锁缓冲区输出被写入输出文件。

【问题讨论】:

  • 您谈论的是进程和线程——不要将两者混为一谈。如果您正在使用 POSIX 线程,那么您的线程函数都具有不正确的签名;它们应该是void *thread1_func(void *unused) { … } 并且应该以return NULL; 结束,尽管这有点没有意义,因为它们现在都有无限循环。您所显示的代码不证明您声称的 1、30 和 120 秒间隔是合理的。
  • 您似乎有一个全局变量FILE *output,线程一时兴起不小心覆盖了它。那是不祥之兆。在thread1_func() 中,你有char *c; 而不是char c; — 哎呀!其他两个功能中的类似投诉。您还没有显示 o1_buff 等全局变量定义。目前尚不清楚主线程是否会访问这些;如果是这样,您就有并发控制问题。
  • 请重新阅读有关如何创建 MCVE (minimal reproducible example) 的信息,并记住在提出此类问题时创建 MCVE。由于此代码中没有free() 调用,因此无法开始猜测问题出在哪里。看起来您使用的是 Mac,或者可能是 BSD 机器。
  • 问题是我只对 3 个文件使用了一个输出文件指针。当我拆分它时,它解决了我的问题。谢谢!

标签: c multithreading output malloc


【解决方案1】:

将 cmets 转换为答案。

您谈论的是进程和线程——不要将两者混为一谈。

如果您使用的是 POSIX 线程,那么您的线程函数都具有不正确的签名;它们应该类似于void *thread1_func(void *unused) { … } 并且应该以return NULL; 结束,尽管这有点没有实际意义,因为它们现在都有无限循环。

您所显示的代码不支持您声称的 1、30 和 120 秒间隔。

  • 您似乎有一个全局变量FILE *output,线程一时兴起不小心覆盖了它。那是不祥之兆。

  • thread1_func() 中,您有一个未初始化的指针char *c; 而不是char c; — 哎呀!其他两个函数中的类似投诉。

您没有显示o1_buff 等全局变量定义。目前尚不清楚主线程是否会访问这些;如果是这样,您就有并发控制问题。

请重新阅读有关如何创建 MCVE (Minimal, Complete, Verifiable Example) 的信息,并记住在提出此类问题时创建 MCVE。

由于此代码中没有free() 调用,因此无法开始猜测问题出在哪里。鉴于崩溃的消息,您看起来像是在 Mac 或 BSD 机器上。

问题在于我只对 3 个文件使用了一个输出文件指针。当我拆分它时,它解决了我的问题。

在线程编程中小心使用全局变量——尤其是共享变量。虽然 POSIX I/O 流保护打开的文件句柄免受线程之间的干扰(有关更多信息,请参阅 flockfile()),但它并不能保护它们免受滥用,例如不同线程中的不同 fopen() 调用导致变量被重置而不考虑哪个线程正在使用它。

最简单的解决方法是将变量设置为线程函数的局部变量;那么就没有干扰了。或者,创建三个全局变量。或者,再次使用互斥锁或类似的访问控制机制来防止线程在使用全局变量时相互干扰。在这种情况下(以及许多其他情况下),将变量设为本地比替代方案更可取。

【讨论】:

  • 我想知道关于 char c 的相同问题。当我只用一个 char c 完成它时,strcat 向我抱怨第二个 arg 不是指针 char,我试图使 char c[] 不能正常工作。如果我将其保留为 char c 然后尝试在 strcat 调用中执行 &c 我得到的值 susch 为 40? 60?等等等等,如果我不询问 strcat 中的地址而只使用 c 我得到一个段错误。此外,我的函数的间隔在我的教授给出的三个不同程序中指定,其中睡眠时间为 1、30、120 秒。同样在我的 pthread_create 我使用 void castin
  • 我刚刚重读了关于文件全局变量问题的最后一点。想来想去,颇有深意。感谢您的提示。
猜你喜欢
  • 2019-06-02
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多