首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >fwrite阻塞线程

fwrite阻塞线程
EN

Stack Overflow用户
提问于 2016-01-29 00:03:04
回答 3查看 961关注 0票数 1

我有一个用c++编写的多线程linux应用程序,运行在i.mx6 arm上。我有一个25lc256SPIEEPROM映射到文件系统。在驱动程序级别,写操作相对较慢,在那里可以做的不多。问题是文件函数阻塞其他线程的时间太长了。睡眠补充似乎没有帮助,似乎我将不得不做一些不同的事情,但对我来说还不清楚该改变什么。

从一个线程调用此函数的输出是

EEprom写 EEprom存于522.000000 703.000000 705.000000 723.000000 662596.000000 1328858.000000 捕获-EPIPE snd_pcm_prepare

我想,由于阻塞的线程,捕获-EPIPE snd_pcm_prepare来自音频缓冲区运行不足的线程。

代码语言:javascript
运行
复制
int SaveCurrentConfig(void) {//EEPROM
    int r = 1;
    struct timeval tvs, tv1, tv2, tv3, tv4, tv5, tv6;
    gettimeofday(&tvs, NULL);
    printf("EEprom write\n");
    pthread_mutex_lock(&eepromconfigmutex);
    {
        char * ConfigXml = BuildXmlConfig();
        FILE * WriteConfig = fopen(ConfigPath, "w");
        if (WriteConfig == NULL) {
            MyLog("Unable to open eeprom %s\n", strerror(errno));
            r = 0;
            goto badfinish;
        }
        gettimeofday(&tv1, NULL);
        size_t len = strlen(ConfigXml);
        unsigned short CRC = ComputeChecksum(ConfigXml, len);
        fwrite((char*) &len, 1, sizeof (size_t), WriteConfig);
        gettimeofday(&tv2, NULL);
        fwrite((char*) &CRC, 1, 2, WriteConfig);
        gettimeofday(&tv3, NULL);
        fwrite(ConfigXml, 1, strlen(ConfigXml), WriteConfig);
        gettimeofday(&tv4, NULL);
        fseek(WriteConfig, ConfigOffset2, SEEK_SET);
        fwrite((char*) &len, 1, sizeof (size_t), WriteConfig);
        fwrite((char*) &CRC, 1, 2, WriteConfig);
        fwrite(ConfigXml, 1, strlen(ConfigXml), WriteConfig);
        gettimeofday(&tv5, NULL);
        fclose(WriteConfig);
badfinish:
        free(ConfigXml);
    }
    pthread_mutex_unlock(&eepromconfigmutex);
    gettimeofday(&tv6, NULL);
    double diff1 = time_diff(tvs, tv1);
    double diff2 = time_diff(tvs, tv2);
    double diff3 = time_diff(tvs, tv3);
    double diff4 = time_diff(tvs, tv4);
    double diff5 = time_diff(tvs, tv5);
    double diff6 = time_diff(tvs, tv6);

    printf("EEprom saved in %f  %f  %f  %f  %f  %f\n", diff1, diff2, diff3, diff4, diff5, diff6);
    return r;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-01-29 03:50:04

如果调用fclose()的线程阻止其他线程长时间运行,那么问题很可能是它在eeprom驱动程序代码中花费了大量时间在内核模式上,清除了挂起的写操作。

有几件事你可以试试:

  • 确保您运行的内核中选择了PREEMPT配置选项。这将允许线程在运行eeprom驱动程序代码时被抢占。
  • 结合第一项建议,为声音线程(和/或eeprom写入线程的较低调度优先级)设置更高的调度优先级。
  • 在编写了较小的数据块后,通过调用fflush(),更改代码以更频繁地将写入清除到eeprom (您可能还需要在底层文件描述符上调用fsync() )。
票数 1
EN

Stack Overflow用户

发布于 2016-01-29 02:13:25

看起来问题就在fclose()中。除非将文件的内容写入磁盘,否则默认情况下,fclose()不会返回。我相信你可以强迫它尽早返回O_NONBLOCK,从man 2 open

O_NONBLOCK或O_NDELAY 如果可能,文件将以非阻塞模式打开。对于返回的文件描述符,open()或任何后续操作都不会导致调用进程等待。有关fifo(命名管道)的处理,请参见fifo(7)。有关O_NONBLOCK与强制文件锁和文件租约一起使用的效果的讨论,请参见fcntl(2)。

您可以尝试使用以下方法:

代码语言:javascript
运行
复制
int fd = open(ConfigPath, O_WRONLY | O_NONBLOCK);
FILE * WriteConfig = fdopen(fd, "w");
票数 0
EN

Stack Overflow用户

发布于 2016-01-29 02:30:05

我会试着

代码语言:javascript
运行
复制
fflush( WriteConfig );

就在你

代码语言:javascript
运行
复制
fclose(WriteConfig);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35074543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档