You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64 Ubuntu环境下libc poll()的P/Invoke签名是否正确?

问题排查与解决线索

1. 修正PollFDStruct结构体定义

Linux中struct pollfd的fd字段是32位int类型,你当前使用的IntPtr在ARM64架构下是64位,会导致结构体内存布局错位——这是poll无法识别套接字事件的核心原因。修正后的结构体如下:

[StructLayout(LayoutKind.Sequential)]
public struct PollFDStruct
{
    public int fd;         // 替换IntPtr为int,匹配Linux文件描述符的int类型
    public short events;   // 要监听的事件
    public short revents;  // 返回的事件
}

2. 修正poll函数的互操作签名

Linux中poll的第二个参数nfds类型是nfds_t,在ARM64架构的Ubuntu系统中它是32位无符号整数(uint),而非你当前使用的64位ulong。参数类型不匹配会导致调用时的参数传递错误,修正后的签名:

[DllImport("libc", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int poll([In, Out] PollFDStruct[] fds, uint nfds, int timeout);

3. 验证事件掩码的正确性

确保你传入的events参数设置了正确的掩码,处理SocketCAN接收事件时,需要设置POLLIN(值为0x001)。如果事件掩码错误,poll也不会检测到预期的事件:

const short POLLIN = 0x001;
var pollFd = new PollFDStruct { fd = canSocketFd, events = POLLIN };
var fds = new[] { pollFd };

4. 检查套接字状态

  • 确认SocketCAN套接字已正确初始化并绑定到对应CAN接口(如can0)
  • 调用poll前,可通过fcntl检查套接字是否处于可读状态,验证数据确实存在
  • 确保没有其他进程或线程占用该套接字的读取权限

5. 优雅关闭线程的补充建议

修正poll调用后,可通过以下方式实现优雅关闭:

  • 新增CancellationToken用于终止线程
  • 在poll循环中定期检查取消信号,或额外监听一个用于唤醒的管道/事件fd,需要关闭时向该fd写入数据,触发poll返回后退出线程循环

内容的提问来源于stack exchange,提问作者Felix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:17:33