Как правильно отключить глубокие C-состояния Linux из программы C?

В ОС Linux процессоры работают в разных состояниях энергосбережения, называемых C-состояниями. Они варьируются от C0 до Cn. C0 — это состояние с максимальной производительностью, но потребляющее больше энергии. Таким образом, для максимизации производительности можно отключить переход в более глубокие состояния. Это можно сделать, записав 0 в файл /dev/cpu_dma_latency.
См.: https://www.quora.com/What-is-the-purpose-of-dev-cpu_dma_latency-device-file-on-Linux-systems

Проблема в том, что есть два способа записи в файл.

  1. Напишите цифру 0.

     FILE *fp;  
    
     void start_low_latency()
     {  
         char target = '0';  
    
         fp= fopen("/dev/cpu_dma_latency", "r+");  
         if (fp == NULL)
         {  
            fprintf(stderr, "Failed to open PM QOS file: %s", strerror(errno));  
            exit(errno);  
         }  
    
         fputc(target, fp);  
       }  
    
     void stop_low_latency()
     { 
         if (fp != NULL)//if (fp == NULL)
           fclose(fp);
     }
    

Ссылка: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_for_real_time/8/html/optimizing_rhel_8_for_real_time_for_low_latency_operation/assembly_controlling-power-management-transitions_optimizing-rhel8-for-real-time-for-low-latency- операция

  1. Двоичная запись числа 0.

     static int laptop = 0;
     static int latency_target_fd = -1;
     static int32_t latency_target_value = 0;  
    
     static void start_low_latency()//static void set_latency_target()
     {
         struct stat s;
         int err;  
    
         if (laptop) {
             warn("not setting cpu_dma_latency to save battery power\n");
             return;
         }  
    
         errno = 0;
         err = stat("/dev/cpu_dma_latency", &s);  
    
         if (err == -1) {
             err_msg_n(errno, "WARN: stat /dev/cpu_dma_latency failed");
             return;
         }
    
         errno = 0;
         latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);  
    
         if (latency_target_fd == -1) {
             err_msg_n(errno, "WARN: open /dev/cpu_dma_latency");
             return;
         }  
    
         errno = 0;
         err = write(latency_target_fd, &latency_target_value, 4);  
    
         if (err < 1) {
             err_msg_n(errno, "# error setting cpu_dma_latency to %d!", latency_target_value);
             close(latency_target_fd);
             return;
         }
         printf("# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
     }
    
     static void stop_low_latency()
     {
         if (latency_target_fd >= 0)
             close(latency_target_fd);
     }
    

Ссылка: https://kernel.googlesource.com/pub/scm/utils/rt-tests/rt-tests/+/stable/devel/v1.0.1/src/cyclotest/cyclotest.c

Какой метод правильный?

the right one? Как определить, что "правильно"?
KamilCuk 11.07.2023 01:57

Я не уверен, что понял вопрос. Я думаю, что один из двух методов делает это неправильно

Cloyz 11.07.2023 02:01

Почему вы так думаете? Что значит «делать это неправильно»?

KamilCuk 11.07.2023 02:02

Один метод записывает число в виде текста, а второй выполняет двоичную запись числа. Они явно разные. Поэтому я думаю, что один из двух методов неверен и не будет работать.

Cloyz 11.07.2023 02:07

Эти два явно разные, но это не означает, что любой из них будет неверным. Возможно, ядро ​​распознает обе альтернативы. Поскольку оба подхода кажутся задокументированными, я думаю, вы должны, по крайней мере, учитывать, что они оба могут работать по желанию.

John Bollinger 11.07.2023 02:23

Спасибо за помощь. «Возможно, ядро ​​​​распознает обе альтернативы». Я не специалист по Linux, но лично меня это удивляет. Есть ли способ убедиться в этом?

Cloyz 11.07.2023 02:30

Вы (после перезагрузки) пробовали od на файле? Если это похоже на некоторые файлы /proc или /sys, вы можете получить текущее значение. А обычно это текстовая строка.

Craig Estey 11.07.2023 02:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно документации ядра,

Чтобы зарегистрировать цель QoS PM по умолчанию для QoS задержки ЦП, процесс должен открыть /dev/cpu_dma_latency.

Пока узел устройства остается открытым, этот процесс имеет зарегистрированный запрос по параметру.

Чтобы изменить запрошенное целевое значение, процесс должен написать s32 в открытый узел устройства. В качестве альтернативы, он может написать шестнадцатеричный строка для значения с использованием формата длиной 10 символов, например. "0x12345678". Это преобразуется в вызов cpu_latency_qos_update_request().

Чтобы удалить запрос пользовательского режима на целевое значение, просто закройте узел устройства.

Обратите внимание, что есть два варианта того, как выразить запрошенное значение C-состояния:

  • записать 32-битное целое число, ИЛИ
  • написать шестнадцатеричную строку

В последнем случае в документах указан формат 10-char, но вполне вероятно, что реализация также принимает более короткие шестнадцатеричные строки. В этом случае каждая из этих альтернатив охватывает один из ваших случаев, что означает, что оба варианта приемлемы.

Другие вопросы по теме