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
相关产品推荐
相关产品推荐

