【发布时间】: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 > 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 时不会重置。