我正在用C语言编写一个简单的应用程序,在树莓派上运行,利用D2XX驱动程序与串口设备通信。我已经按照很多在线教程和参考指南进行了操作,例如设置自定义udev规则以确保驱动程序可以正确加载,按照FTDI的构建说明安装共享库,使用gcc的
现在,我正在尝试将我的简单程序转换为守护进程,可以通过init.d脚本(如
为简单起见,这里是一个简化版本的C程序,可以正常工作: myprog.c:
我使用
我以完全相同的方式编译该程序:
换句话说,一旦它尝试在分叉的进程中调用D2XX驱动程序,它就会失败。我做错了什么?我已经通过第一个示例证明代码是有效的,那么作为守护进程运行时导致它完全崩溃的原因是什么?据我所知,它甚至没有机会执行相关的D2XX方法;似乎它根本找不到该方法,而在分叉的进程中运行时出现了这种情况。
-l
参数链接库进行编译,以及使用sudo
运行我的C程序以确保驱动程序具有适当的访问权限。这些都取得了成功!程序按预期工作。现在,我正在尝试将我的简单程序转换为守护进程,可以通过init.d脚本(如
service start
)进行控制,并遇到了麻烦。为简单起见,这里是一个简化版本的C程序,可以正常工作: myprog.c:
#include <stdlib.h>
#include "ftd2xx.h"
int main(int argc, char *argv[])
{
DWORD i, iNumDevs = 0;
char *serialNumber = malloc(64);
FT_STATUS ftStatus = FT_CreateDeviceInfoList(&iNumDevs);
for (i = 0; i < iNumDevs; i++) {
ftStatus = FT_ListDevices((PVOID)i, serialNumber, FT_LIST_BY_INDEX|FT_OPEN_BY_SERIAL_NUMBER);
if (FT_OK == ftStatus) {
break;
}
}
// more code here...
return EXIT_SUCCESS;
}
我使用
gcc -lftd2xx -o myprog myprog.c
编译它,然后使用sudo ./myprog
运行它,相信我它确实完成了应该完成的一切。但是现在我正试图将这个相同的代码改为一个守护进程,我一直在遵循其他一些在线教程,并且上面的代码已经转换成更像这样子的东西。目前,这个不起作用:
mydaemon.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "ftd2xx.h"
int main(int argc, char *argv[])
{
pid_t pid, sid;
pid = fork();
if (pid < 0) {
return EXIT_FAILURE;
}
if (pid > 0) {
return EXIT_SUCCESS;
}
umask(0);
openlog("mydaemon", LOG_PID|LOG_CONS, LOG_USER);
sid = setsid();
if (sid < 0) {
syslog(LOG_ERR, "Failed to set session ID on child process");
return EXIT_FAILURE;
}
if ((chdir("/")) < 0) {
syslog(LOG_ERR, "Failed to change working directory");
return EXIT_FAILURE;
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
while (1) {
DWORD i, iNumDevs = 0;
char *serialNumber = malloc(64);
syslog(LOG_INFO, "I get to this line");
FT_STATUS ftStatus = FT_CreateDeviceInfoList(&iNumDevs);
syslog(LOG_INFO, "I do not get to this line :( ");
// more code here...
sleep(10);
}
return EXIT_SUCCESS;
}
我以完全相同的方式编译该程序:
gcc -lftd2xx -o mydaemon mydaemon.c
;我以相同的方式运行它:sudo ./mydaemon
,但不幸的是它无法工作。在另一个控制台窗口中,我正在追踪/var/log/messages
文件,并且我可以清楚地看到它到达了我的第一条日志消息(即“我可以到达这一行”),但紧接着它就停滞不前了。我从未看到第二条日志消息,而且在此时,程序变得完全无响应。我必须找到它的进程ID并杀死它。换句话说,一旦它尝试在分叉的进程中调用D2XX驱动程序,它就会失败。我做错了什么?我已经通过第一个示例证明代码是有效的,那么作为守护进程运行时导致它完全崩溃的原因是什么?据我所知,它甚至没有机会执行相关的D2XX方法;似乎它根本找不到该方法,而在分叉的进程中运行时出现了这种情况。
gcc -o mydaemon mydaemon.c /usr/local/lib/libftd2xx.a -lpthread -Wl,--no-as-needed -ldl
。不幸的是,这也没有起作用。它编译了,但最终仍然遇到完全相同的问题。 - soapergemvfork
而不是fork
,那么它就可以工作了。唯一的问题是当你使用vfork
时,父进程不会自动终止。我可以手动杀死它,子进程继续运行,并继续成功访问D2XX函数。但是,我真的希望能够使用常规的fork
来使其工作...我不想编写脚本每次都杀死父进程,因为这似乎是一个廉价的解决方法。我更愿意找出根本问题并在代码中解决它。 - soapergem-f
选项跟踪forks,可能会有所帮助,通过strace
程序来查看它在哪里卡住了。 - Dolda2000std{in,out,err}
而不替换它们并不总是一个好主意。即使您的程序对它们没有任何操作,某些库可能会假定它们存在于各种目的(即使它们不应该存在)。当然,如果这个libftd2xx
是那些在stderr
上输出虚假消息的糟糕编写的库之一(我自己没有经验),那么这可能是许多麻烦的根源。 - Dolda2000EXIT_SUCCESS
退出,则处理这些进程会更加方便。 - Dolda2000