Создание потоков linux в реальном времени из bash и планирования linux

Я новичок в разработке ядра Linux. Я пытался изучить создание и синхронизацию потоков. Моя конечная цель - создать два потока, и эти два потока используют общий ресурс, охраняемый семафором.

Код

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<semaphore.h>

sem_t sema_obj;

pthread_t tid[2];

int shared_val = 0;

void* doSomeThing(void *arg)
{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    for(i=0;i<5;i++){
    printf("\n going to wait %x\n",(unsigned int)id);
    sem_wait(&sema_obj);
    shared_val++;
    sleep(1);
    printf("\n %d The value of shared_val is %d in thread %x \n",(int)i, shared_val, (unsigned int)id);
    sem_post(&sema_obj);
    printf("\n gave up sem %x\n",(unsigned int)id);
    }

    for(i=0; i<(0xFFFFFFFF);i++);

    return NULL;
}

int main(void)
{
    int i = 0;
    int err;
    sem_init(&sema_obj, 0, 1);
    while(i < 2)
    {
    pthread_attr_t attr;
    struct sched_param param;

    pthread_attr_init(&attr);
    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    param.sched_priority = 50;
    pthread_attr_setschedparam(&attr, &param);
    //sched_setscheduler(current, SCHED_FIFO, &param);
        err = pthread_create(&(tid[i]), &attr, &doSomeThing, NULL);
    //err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        if (err != 0)
            printf("\ncan't create thread :[%s]", strerror(err));
        else
            printf("\n Thread created successfully 0x%X \n",(unsigned int)tid[i]);

        i++;
    }
    enter code here
    sleep(60);
    return 0;
}

Я компилирую это с

gcc -o threads_op -pthread -lrt threads.c

После запуска кода я вижу:

 Thread created successfully 0xB75CBB40 

 going to wait b75cbb40

 Thread created successfully 0xB6DCAB40 

 going to wait b6dcab40

 0 The value of shared_val is 1 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 1 The value of shared_val is 2 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 2 The value of shared_val is 3 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 3 The value of shared_val is 4 in thread b75cbb40 

 gave up sem b75cbb40

 going to wait b75cbb40

 4 The value of shared_val is 5 in thread b75cbb40 

 gave up sem b75cbb40

 0 The value of shared_val is 6 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 1 The value of shared_val is 7 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 2 The value of shared_val is 8 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 3 The value of shared_val is 9 in thread b6dcab40 

 gave up sem b6dcab40

 going to wait b6dcab40

 4 The value of shared_val is 10 in thread b6dcab40 

 gave up sem b6dcab40

RTPRIO для этого процесса - '-', S 1000 4551 4338 - 00:00:00 threads_op

Были следующие вопросы,

1) Почему поток не работает в режиме реального времени и принимает приоритет, который я устанавливаю?

2) Почему семафор не блокируется поочередно двумя потоками и не обновляет общую переменную? У двух потоков одинаковый приоритет.

Если вы знаете пошаговое руководство, чтобы понять темы ядра Linux, поделитесь.


person PKVJ    schedule 16.11.2015    source источник
comment
Почему есть ссылка на Баш?   -  person Basilevs    schedule 16.11.2015
comment
Вы не должны использовать спящий режим для приложений реального времени, поскольку это только минимальная гарантия времени, то есть ваш поток будет ждать не менее 1 секунды, а затем у вас будет гранулярность времени вашей системы вдобавок к этому.   -  person g24l    schedule 16.11.2015
comment
На самом деле пробуждение для сна будет более точным для потока в реальном времени. Но у sleep () есть только вторая степень детализации.   -  person Jon Watte    schedule 03.11.2018


Ответы (2)


Несколько вещей.

Во-первых, я ненавижу придираться к вещам, но вы не занимаетесь разработкой ядра для linux. Вы пишете многопоточное приложение, работающее в Linux. Таким образом, тег linux-kernel неуместен. Разработка ядра заключается в написании кода, встроенного в ядро, такого как планировщики, драйверы устройств, драйверы файловой системы и т. Д.

У вас есть сон внутри критического раздела (например, между sem_wait и sem_post). Вы испытываете "голодание нитей". См. Мой ответ здесь: Синхронизация потоков C ++

Поскольку вы используете pthreads, вам, вероятно, будет лучше с pthread_mutex_lock/pthread_mutex_unlock.

Вы также используете printfs. Они нарушают сроки даже для отладки.

Вы пытаетесь выполнить SCHED_FIFO, но не проверяете код возврата. Только root может устанавливать некоторые планировщики RT и / или более высокие приоритеты. Точно так же для приоритета планирования.

Ух ты! Приоритет 50 для SCHED_FIFO? Если вы его действительно получили, все, что выше 11, назначит вам более высокий приоритет, чем некоторые внутренние потоки ядра. Вы, вероятно, заблокировали бы систему. [*]

На той стадии, на которой вы находитесь, прежде чем вы начнете «все в» [с планировщиком RT и т. Д.], Работайте с обычным планировщиком со стандартным приоритетом. Вы будете поражены тем, насколько хорошо он будет работать. Прежде чем поднять напряжение, сначала отладьте код / ​​логику синхронизации потоков.

На самом деле, для плавного, высокочувствительного RT-приложения, которое детерминировано с низкой задержкой, я думаю, вам нужно немного больше спланировать, как вы будете синхронизировать, какие очереди между потоками, типы блокировки ( например, RCU, попытки блокировки, таймауты при попытках блокировки и т. д.) Сколько потоков вам понадобится? Что будет делать каждый? У вас есть псевдокод для каждого? Какой тип среды потока (например, потребитель / производитель, главный / подчиненный / рабочий). Собираются ли ваши потоки «украсть работу»? И т. Д. И т. Д. Будете ли вы использовать обмен сообщениями IPC, разделяемую память? Сколько данных? Какая пропускная способность для данных между потоками?

[*] Причина, по которой я это знаю, заключается в том, что я был разработчиком системы реального времени, которая имела 50 потоков, 8 ядер и постоянное взаимодействие с несколькими драйверами устройств и FPGA, а также огромное количество DMA [настолько, что нам пришлось измерить это с анализатором шины PCIe, чтобы убедиться, что у шины достаточно пропускной способности]. Теперь это продукт для отгрузки.

person Craig Estey    schedule 16.11.2015

Чтобы ответить на вопросы:

1) Как узнать, что поток не в реальном времени? Процесс в реальном времени отличается от потока в реальном времени. Если вы запустите эту программу с помощью sudo или root, она должна получить приоритет в реальном времени.

2) Справедливость семафоров не гарантируется. если вы хотите, чтобы другой поток имел возможность увеличить значение, вы должны переместить вызов sleep () за пределы критического раздела с семафором. Публикация (освобождение) семафора не обязательно вызывает перепланирование, и, таким образом, вполне возможно, чтобы освобождающий поток немедленно вернулся в цикл и снова дождался (получил) семафор.

person Jon Watte    schedule 03.11.2018