【发布时间】:2013-06-11 16:18:08
【问题描述】:
我需要为 Linux sched_setaffinity 函数提供 P/Invoke 签名,以便从运行在 Mono 上的 C# 代码调用。
int sched_setaffinity(pid_t pid, size_t cpusetsize,
cpu_set_t *mask);
“open-hardware-monitor”项目中的ThreadAffinity类将其定义为:
[DllImport(LIBC)]
public static extern int sched_setaffinity(int pid, IntPtr maskSize,
ref ulong mask);
但是,Mono.LibRt 项目使用不同的签名:
[DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
SetLastError=true, EntryPoint="sched_setaffinity")]
protected static extern int sched_setaffinity (long pid, int num_bytes,
byte[] affinity);
两个签名都正确,还是一个错误?它们是否可跨 32 位和 64 位架构移植?
我假设第一个参数应该是 int,而不是 long,因为 pid_t 在 32 位和 64 位平台上都是有符号的 32 位整数(根据 Joe Shaw)。同样,第二个应该是UIntPtr 或IntPtr per Patrick McDonald。但是,我不知道如何处理第三个参数。
编辑:基于 Simon Mourier 的评论:我从 cpu_set_t * 类型中收集到第三个参数应该是一个指针。 ref ulong 是否符合条件?我很想使用这种类型,因为它使宏更容易实现;例如,单个处理器id 的掩码可以计算为:
ulong mask = 1UL << id;
我在这个sched.h 中找到了cpu_set_t 的定义,它被实现为unsigned long int 的数组。
【问题讨论】:
-
我同意
int pid和IntPtr maskSize。对于 cpu_set_t,我想它默认为 Cint,因为它没有在 sched.h 中明确定义。重要的是它必须是一个指针,并且这个指针必须由内部 CPU_* 宏(CPU_ZERO 等)操作。因此您可以使用 byte[] 或 int[],但您还需要将 CPU_* 宏暴露给 .NET 世界。