微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我的D2XX应用程序在分叉时不起作用?

我在C中编写一个简单的应用程序,在RaspBerry Pi上运行,它利用 D2XX drivers与串口设备进行通信.我已经按照一些在线教程和参考指南来实现它,并采取了诸如设置自定义udev规则以确保驱动程序可以正确加载的步骤,我按照FTDI的构建说明安装共享库,我使用-l参数在编译时链接到库中的gcc,我用sudo运行我的C程序以确保驱动程序具有适当的访问权限.这是成功的!该计划按预期工作.

现在我正在尝试将我的简单程序转换为可以使用init.d脚本(la 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方法;就好像在分叉进程中运行时,它首先无法找到方法.

解决方法

可能是因为它使用了libusb ……而且它们看起来很糟糕.

在这里看到我的问题:libusb-1.0 hotplug events stop working in parent after fork(),when child calls libusb_exit()

这里的讨论是:https://github.com/libusb/libusb/issues/268

我的具体问题与hotplug事件有关,但我希望其他事情也会出错.

在你的场景中这不那么明显的原因是因为他们可能在库加载时会做一些setup / init(它们是怎样的),而不是在你开始使用它的时候.

正如@duskwuff所指出的,这里有另一个答案:https://stackoverflow.com/a/35186414/149341

我刚做了一些游戏,请按照以下步骤进行操作:

cd $(mktemp -d)
curl http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx-x86_64-1.3.6.tgz | tar -xvz

把它放在test.c中:

#include <stdio.h>
#include "ftd2xx.h"

int main(void) {
    int num_devs;

    fprintf(stderr,"in to main()\n");

    FT_STATUS ft_status = FT_CreateDeviceInfoList(&num_devs);
    fprintf(stderr,"FT_CreateDeviceInfoList() returned: %d\n",ft_status);

    fprintf(stderr,"out of main()\n");

    return 0;
}

编译:

gcc test.c -o test -g -I release -L release/build -lftd2xx -ldl -lpthread

现在在gdb中:

[...]
Reading symbols from test...done.
(gdb) b libusb_init
Breakpoint 1 at 0x40cd20
(gdb) start
Temporary breakpoint 2 at 0x401d75: file test.c,line 7.
Starting program: /tmp/tmp.jJpBNywVzB/test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1,0x000000000040cd20 in libusb_init ()
(gdb) bt
#0  0x000000000040cd20 in libusb_init ()
#1  0x0000000000401f36 in my_init ()
#2  0x000000000041a05d in __libc_csu_init ()
#3  0x00007ffff7614ed5 in __libc_start_main (main=0x401d6d <main>,argc=1,argv=0x7fffffffe228,init=0x41a010 <__libc_csu_init>,fini=<optimised out>,rtld_fini=<optimised out>,stack_end=0x7fffffffe218)
    at libc-start.c:246
#4  0x0000000000401ca9 in _start ()
(gdb)

它在libusb_init()之前达到了断点,甚至在从my_init()调用main()之前.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐