【问题标题】:Why does FT_Read() fail in the child process but work in the parent process?为什么 FT_Read() 在子进程中失败但在父进程中工作?
【发布时间】:2016-02-02 21:37:32
【问题描述】:

我有以下程序,它使用 ftd2xx 库向 USB 设备写入一个字节,然后读取回复。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include "../ftd2xx.h"

void fatal (const char *format,...) {
  va_list argp;
  fprintf(stderr, "FATAL: ");
  va_start(argp, format);
  vfprintf(stderr, format, argp);
  va_end(argp);
  fprintf(stderr, "\n");
  exit(3);
}

int main(int argc, char* argv[]) {
  int pid = fork();
  if (pid > 0) { //replace with: if (pid == 0) {
    FT_STATUS ftStatus;
    printf("before FT_OpenEx\n");
    FT_HANDLE ftHandle;  
    if ((ftStatus = FT_OpenEx("DA011SCV", FT_OPEN_BY_SERIAL_NUMBER, &ftHandle)) != FT_OK) fatal("FT_OpenEx failed");
    printf("before FT_Write\n");
    uint8_t buffer[1];
    buffer[0] = 0x55;
    DWORD bytesWritten;
    if ((ftStatus = FT_Write(ftHandle, buffer, sizeof(buffer), &bytesWritten)) != FT_OK) fatal("FT_Write failed");
    printf("before FT_Read\n");
    DWORD bytesRead;
    if ((ftStatus = FT_Read(ftHandle, buffer, 1, &bytesRead)) != FT_OK) fatal("FT_Read failed");
    if (bytesRead > 0) {
      printf("FT_Read data=0x%02X\n", buffer[0]);
    } else {
      printf("FT_Read no data\n");
    }
    printf("before FT_Close\n");
    if ((ftStatus = FT_Close(ftHandle)) != FT_OK) fatal("FT_Close failed");
    printf("press Enter to exit\n");
  }
  getchar();
  exit(0);
}

如图所示的代码产生这个输出:

//Output if (pid > 0)
before FT_OpenEx
before FT_Write
before FT_Read
FT_Read data=0x55
before FT_Close
press Enter to exit

但是,如果我将第一个if 的条件从(pid &gt; 0) 更改为(pid == 0),即如果我在子进程中进行USB 通信,那么程序会在FT_Read() 函数和输出中挂起是:

//Output if (pid == 0)
before FT_OpenEx
before FT_Write
before FT_Read

为什么会这样?

一些细节:

  • 设备中的USB芯片为FT240X,出厂设置。
  • USB 设备就像一个回声:它接收到的每个字节都会立即发回。
  • 我使用协议分析器检查了传输的字节值是否正确。
  • ftd2xx 库版本为 1.1.12。

【问题讨论】:

  • 如果在你 fork 之后再次执行你的镜像(并检测到这种情况,这样你就不会无休止地执行它)会发生什么?听起来像是由 FTDI 库维护的某种全局状态(通过头文件?)被分叉破坏了。
  • 您在哪个平台上看到了这种行为?
  • @antiduh 在execve() 在孩子中FT_Read() 工作后。我会尝试这种方法,尽管我仍然想知道为什么简单的fork() 不起作用。
  • @duskwuff 是 OpenSuse/Linux,uname -a 的输出是:Linux linux 3.11.6-4-desktop #1 SMP PREEMPT Wed Oct 30 18:04:56 UTC 2013 (e6d4a27) x86_64 x86_64 x86_64 GNU/Linux
  • @tom - FTDI 库代码中存在错误。他们正在建立某种全局状态,也许是互斥体。阅读 fork 上的手册页,很多状态在你 fork 时不会重置。

标签: c linux fork ftdi


【解决方案1】:

您所描述的听起来好像 ftd2xx 库中存在错误 - 库在加载时可能会执行一些初始化,而当进程 ID 更改时它会变得无效。

ftd2xx 库是封闭源代码,并根据禁止逆向工程的许可证分发,因此我无法确定发生了什么。您可能想尝试使用开源 FTDI 库,例如 libftdi

【讨论】:

    【解决方案2】:

    图书馆很奇怪 - 我遇到了同样的问题。对我来说,它有助于在调用fork() 后动态加载库。查看这篇帖子https://stackoverflow.com/a/7626550/907675,了解如何从库中动态加载函数。

    【讨论】:

    • 我在我正在处理的项目中遇到了与 libftd2xx 相同的问题,并且想知道:您是否必须通过创建指向它的指针来动态调用每个 D2XX 函数先用dlsym?还是只调用一次然后按名称调用函数就足够了?
    • @SoaperGEM:我认为当您动态加载库时,您必须通过 dlsym 检索到的指针调用每个函数(我就是这样做的)。如果您按名称调用函数,您将以静态方式使用该库。顺便说一句,ftd2xx 在 Linux 上相当垃圾,我终于不得不切换到 libftdi,我更开心了。
    • 好的,非常感谢。我将检查 libftdi;听起来很多人更喜欢那个而不是官方图书馆!
    猜你喜欢
    • 1970-01-01
    • 2017-06-29
    • 2020-01-22
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多