2013-06-14 2 views
0

Мне нужно придумать подпись P/Invoke для функции Linux sched_setaffinity, которая вызывается из кода C#, работающего на Mono.P/Invoke для sched_setscheduler

int sched_setaffinity(pid_t pid, size_t cpusetsize, 
         cpu_set_t *mask); 

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-битовым целым числом на обоих 32- и 64-разрядные платформы (на Joe Shaw). Аналогичным образом, второй должен быть UIntPtr или IntPtr за Patrick McDonald. Однако я не знаю, как обрабатывать третий параметр.

Редактировать: На основе комментария Симона Моурье: Я собираю от cpu_set_t * тип, что третьим параметром должен быть указатель. Имеются ли ref ulong? Я склонен использовать этот тип, потому что он упрощает реализацию макросов; например, маска для одного процессора id может быть вычислена как:

ulong mask = 1UL << id; 

Я нашел определение для cpu_set_t в этом sched.h, в которой он реализован как массив unsigned long int.

+0

Я согласен с 'int pid' и' IntPtr maskSize'. Для cpu_set_t я полагаю, что он по умолчанию имеет значение C 'int', поскольку он явно не определен в sched.h. Важно то, что это должен быть указатель, и этот указатель должен управляться внутренними макросами CPU_ * (CPU_ZERO и т. Д.). Таким образом, вы можете использовать byte [] или int [], но вам также нужно выставить макросы CPU_ * в мир .NET. –

ответ

1

Как вы нашли, cpu_set_t - это просто массив беззнакового длинного int. Поэтому я бы объявил функцию следующим образом:

[DllImport("libc.so.6", SetLastError=true)] 
private static extern int sched_setaffinity(
    int pid, 
    IntPtr cpusetsize, 
    ulong[] cpuset 
); 
+0

Спасибо David! Я полагаю, что 'cpusetsize' должен быть размером всего массива (например,' 4 * sizeof (ulong) ', если он содержит четыре элемента)? – Douglas

+0

(Мне потребуется несколько недель, чтобы проверить ответ, в настоящее время у меня нет доступа к машине Linux.) – Douglas

+0

Да. Документы указывают, что это количество байтов. –

0

По моему other answer, я пошел с прежним вариантом (который отлично работал на Linux).

[DllImport("libc.so.6", SetLastError=true)] 
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize, 
              ref ulong cpuset); 
+0

Проблема в том, что 'cpu_set_t' может быть больше, чем' ulong'. –

+0

@DavidHeffernan: для этого потребуется машина размером более 64-х ядерная, нет? – Douglas

+0

Такие машины существуют –

Смежные вопросы