【问题标题】:posix_spawn pipe dmesg to python scriptposix_spawn 管道 dmesg 到 python 脚本
【发布时间】:2021-10-10 01:52:30
【问题描述】:

我的测试系统中有几个 USB 转 422 适配器。我已经使用 FTProg 为每个适配器指定了一个特定的名称:Sensor1、Sensor2 等。它们都将在开机时插入。我不想将每个适配器硬编码到特定的 ttyUSBx。我希望驱动程序弄清楚它需要使用哪个 tty。我正在为 linux 系统开发 C 语言。我的第一个想法是在我的启动代码中使用类似的东西。

system("dmesg | find_usb.py");

python 脚本会找到设备,因为每个设备都有唯一的产品描述。然后使用 USB 树将每个设备与其 ttyUSBx 相关联。然后,该脚本将创建 /tmp/USBDevs,它只是一个简单的 device:tty 配对,便于 C 代码搜索。

有人告诉我...不要使用系统...使用 posix_spawn()。但是我在将 dmesg 的输出通过管道传输到我的 python 脚本时遇到了问题。这不起作用

char *my_args[] = {"dmesg", "|", "find_usb.py", NULL};
pid_t pid;
int status;

status = posix_spawn(&pid, "/bin/dmesg", NULL, NULL, my_args, NULL);
if(status == 0){
   if(waitpid(pid, &status, 0) != -1);{
printf("posix_spawn exited: %i", status);
}

我一直试图弄清楚如何使用 posix_spawn_file_actions() 来做到这一点,但我不允许在工作中达到“鲍尔默曲线”的峰值。

提前致谢

【问题讨论】:

    标签: c linux posix embedded-linux


    【解决方案1】:

    不要使用/dev/ttyUSB* 设备,而是编写 udev 规则来生成设备的命名符号链接。有关简要操作方法,请参阅 here。基本上,每个设备都有一个 udev 规则,以 SYMLINK+=Sensor-name 结尾,在你的程序中,每个传感器使用 /dev/Sensor-name。 (我确实建议使用Sensor- 前缀,注意首字母大写,因为目前所有设备名称都是小写的。这样可以避免与现有设备发生任何冲突。)

    这些符号链接只有在插入匹配设备时才会存在,并且会指向正确的设备(在这种情况下是 /dev/ttyUSB*)。移除设备后,udev 也会自动删除符号链接。只需确保您的 udev 规则准确识别设备(不仅是供应商:设备,还有序列号)。我希望规则看起来像

    SUBSYSTEM=="tty", ATTRS{idVendor}=="VVVV", ATTRS{idProduct}=="PPPP", ATTRS{serial}=="SSSSSSSS", SYMLINK+="Sensor-name"
    

    其中VVVV 是 USB 供应商 ID(四个十六进制数字),PPPP 是 USB 产品 ID(四个十六进制数字),SSSSSSSS 是序列号字符串。您可以使用例如查看这些值udevadm info -a -n /dev/ttyUSB* 插入设备时。

    如果你仍然坚持解析 dmesg 输出,使用你自己的脚本是个好主意。

    您可以使用FILE *handle = popen("dmesg | find_usb.py", "r"); 并从handle 读取,就像它是一个文件一样。完成后,使用int exitstatus = pclose(handle); 关闭句柄。请参阅man popenman pclose 了解详细信息,man 2 wait 了解WIFEXITED()WEXITSTATUS()WIFSIGNALED()WTERMSIG() 宏,您需要使用它来检查exitstatus(尽管在您的情况下,我想你可以忽略任何错误)。

    如果您确实想使用posix_spawn()(或大致等价的fork()execvp()),您需要设置至少一个管道(读取生成命令的输出)——如果是两个你 spawn/fork+exec 两个 dmesg 和你的 Python 脚本——这变得有点复杂。有关详细信息,请参阅man pipe。就个人而言,我会重写 Python 脚本,以便它在内部执行 dmesg 本身,并且只输出设备名称。使用posix_spawn(),您将使用三个操作初始化posix_file_actions_t:_adddup2() 将管道的写入端复制到STDOUT_FILENO,两个_addclose() 用于关闭管道的两端。不过,我自己更喜欢使用fork()exec(),有点类似于示例by Glärbo in this answer

    【讨论】:

    • 感谢您的回复。我没有结婚使用posix_spawn。我是这个团队的新手,在我职业生涯的大部分时间里,我一直在为小型嵌入式传感器编写裸机 C。我尝试在另一段代码中使用“系统”。我的合并请求被立即拒绝,我被告知使用 posix_spawn 所以我只是想再次避免这种命运。创建一个 udev 规则看起来是解决这个问题的一种非常干净的方法,我想我会在星期一深入研究安装脚本并删除我的代码中看起来像这样的 cmets。 // 不要使用系统 // ¯_(ツ)_/¯ system("dmesg | find_usb.py);
    最近更新 更多