#c #linux #kernel #driver
#c #linux #ядро #драйвер
Вопрос:
Я пытаюсь реализовать программу для считывания данных с тактильных датчиков, но у меня проблемы с высокой загрузкой процессора. Мне нужна помощь, чтобы уменьшить нагрузку на процессор.
Моя настройка
Я считываю данные с нескольких (до 16) тактильных датчиков. Датчики подключены через usb к моему компьютеру. В Linux эти устройства создают виртуальные последовательные порты: /dev/ttyACM0, /dev/ttyACM1, /dev/ttyACM2 …
Это то, что сообщает мне dmesg, когда я подключаю датчики (вывод для одного датчика):
[ 321.998462] usb 2-2: отключение USB, номер устройства 3 [ 327.541414] usb 2-2: новое высокоскоростное USB-устройство № 5 с использованием ohci_hcd [ 327.998963] usb 2-2: найдено новое USB-устройство, idVendor= 0471, idProduct=0889 [ 327.998983] usb 2-2: строки нового USB-устройства: Mfr=1, Product=2, SerialNumber=3 [ 327.998997] usb 2-2: Продукт: WTS [ 327.999011] usb 2-2: Производитель: Weiss Robotics [ 327.999024] usb 2-2: серийный номер: 0001 [ 328.035356] cdc_acm 2-2:1.0: это устройство не может выполнять вызовы самостоятельно. Это не модем. [ 328.035424] cdc_acm 2-2:1.0: ttyACM0: устройство USB ACM
Я использую termios из termios.h для открытия последовательного устройства. Поскольку датчики имеют двоичный протокол, я устанавливаю устройство на неканонический и использую необработанный вывод. Датчики обеспечивают функцию периодической выборки, которая будет отправлять около 270 кадров данных в секунду.
Моя программа должна считывать и обрабатывать кадр с последовательного устройства, как только будет доступен полный кадр.
Проблема: высокая загрузка процессора
Это то, что в основном делает мой код:
int fd = open("/dev/ttyACM0");
struct termios settings;
settings.xxx = ... // see full code for details
tcflush( fd, TCIFLUSH );
tcsetattr( fd, TCSANOW, amp;settings );
while(1)
{
Frame f = readCompleteFrame(fd);
processFrame(f);
}
Когда я перевожу устройство в режим блокировки чтения и выполняю свой цикл, загрузка процессора составляет около 15%. У меня есть отдельный поток для каждого датчика. Поскольку у меня несколько датчиков, каждый поток будет потреблять 15% одного ядра процессора.
Я профилировал программу с помощью команды time: почти все процессорное время тратится в ядре. Время пользователя близко к нулю.
Что я пытался исправить
- Я перевел устройство в неблокирующий режим и использовал опрос из sys/poll.h. Загрузка процессора такая же: 15% на датчик.
- Я перевел устройство в неблокирующий режим и использовал select из unistd.h. Тот же результат, что и при опросе.
- Я перевел устройство в неблокирующий режим и продолжал вызывать read(fd); usleep(1); пока не получил некоторые данные. Это использует 50% ЦП, но не зависит от количества датчиков.
Полный тестовый код
Полный код, который я использовал для тестирования, можно найти здесь: http://pastebin.com/7dv0U2nN
Комментарии:
1. Я хотел бы увидеть здесь больше вопросов для начинающих, подобных этому.
Ответ №1:
Изучив код, вы, вероятно, мало что можете сделать, чтобы исправить это в своем приложении.
Вероятно, нагрузка вызвана проблемой в драйвере ядра или тем, как USB-устройство взаимодействует с ПК.