Pthreads с приоритетом в реальном времени - PullRequest
6 голосов
/ 08 июля 2010

Мне нужно управлять пулом потоков с разными приоритетами, поэтому я написал следующую процедуру запуска потока:

static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
    pthread_attr_t attr;
    int err;
    struct sched_param param = {
        .sched_priority = prio
    };

    assert(pthread_attr_init(&attr) == 0);
    assert(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0);
    assert(pthread_attr_setschedparam(&attr, &param) == 0);
    err = pthread_create(&thrd->handler, &attr, thread_routine, (void *)thrd);
    pthread_attr_destroy(&attr);

    return err;
}

В принципе непривилегированный пользователь не должен иметь права выполнять этот код: вызов pthread_create () должен возвращать EPERM из-за последствий для безопасности запуска потока с высоким приоритетом.

Неожиданно он работает для обычного пользователя, но он вообще не уважает данный приоритет.

Я попытался изменить код, удалив pthread_attr_t и установив атрибут планирования после создания потока:

static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
    pthread_attr_t attr;
    int err;
    struct sched_param param = {
        .sched_priority = prio
    };

    err = pthread_create(&thrd->handler, NULL /*&attr*/, thread_routine,
                         (void *)thrd);
    if (err != 0) return err;

    err = pthread_setschedparam(thrd->handler, SCHED_FIFO, &param);
    if (err != 0) return err;

    return err;
}

Кстати, этим подходом гораздо сложнее управлять, так как в случае ошибки мне нужно уничтожить только что созданный поток. По крайней мере, кажется, что он работает должным образом в отношении требований к разрешениям (это может выполнить только root), но приоритеты все еще не соблюдаются.

Я что-то не так делаю?

EDIT

Я только что добавил следующий фрагмент кода, который выполняется каждым потоком:

static
void getinfo ()
{
    struct sched_param param;
    int policy;

    sched_getparam(0, &param);
    DEBUG_FMT("Priority of this process: %d", param.sched_priority);

    pthread_getschedparam(pthread_self(), &policy, &param);

    DEBUG_FMT("Priority of the thread: %d, current policy is: %d and should be %d",
              param.sched_priority, policy, SCHED_FIFO);
}

При первом методе (а именно pthread_attr_t подход) выясняется, что pthread_attr_setschedpolicy совершенно не эффективна, поскольку приоритет равен 0, а политика не SCHED_FIFO.

При втором методе (а именно pthread_setschedparam подход) функция печатает ожидаемые данные, но выполнение продолжает вести себя неправильно.

1 Ответ

8 голосов
/ 09 июля 2010

Я думаю, вы также должны использовать pthread_attr_setinheritsched, чтобы гарантировать, что ваши изменения в настройке приоритета будут приняты во внимание.Со страницы man:

PTHREAD_INHERIT_SCHED Указывает, что политика планирования и связанные атрибуты должны наследоваться от потока создания, а атрибуты планирования в этом аргументе attr должны игнорироваться.

PTHREAD_EXPLICIT_SCHED Указывает, что для политики планирования и связанных атрибутов должны быть установлены соответствующие значения из этого объекта атрибута.

И чуть дальше на странице man вы получите:

Значением по умолчанию для атрибута attribute-scheduler в недавно инициализированном объекте атрибутов потока является PTHREAD_INHERIT_SCHED.

...