Что должна делать программа C в простое при работе в Linux?
Я написал много программ на Си для микроконтроллеров, но никогда не работал на ОС, такой как Linux. Как linux решает, сколько времени уделить обработке моего приложения? Есть ли что-то, что мне нужно сделать, когда у меня есть время простоя, чтобы сказать ОС пойти и сделать что-нибудь еще и вернуться ко мне позже, чтобы другие процессы могли также получить время для запуска? Или ОС просто делает это автоматически?
Изменить: Добавление более подробной информации Моя программа c имеет планировщик задач. Некоторые задачи выполняются каждые 100 мс, некоторые - каждые 50 мс и т. Д. В моем основном цикле программы я вызываю ProcessTasks, которая проверяет, готовы ли какие-либо задачи к запуску, если ни одна из них не готова, она вызывает функцию ожидания. Функция холостого хода ничего не делает, но она есть, чтобы я мог переключать вывод GPIO и контролировать время простоя с помощью оптического прицела... или чего-то еще, если я так хотел. Так что, может быть, мне следует вызвать sched_yield() в этой простой функции???
3 ответа
Как linux решает, сколько времени уделить обработке моего приложения
Каждый планировщик решает сам. Некоторые вознаграждают вас за то, что вы не использовали свою долю, некоторые бросают кубики, пытаясь предсказать, что вы будете делать и т. Д. По моему мнению, вы можете просто считать это магией. После того, как мы входим в цикл, планировщик волшебным образом решает, что наше время истекло и т.д.
Есть ли что-то, что мне нужно сделать, когда у меня есть простой, чтобы сказать ОС, чтобы сделать что-то еще
Вы могли бы позвонить sched_yield
, Я никогда не называл это, и при этом я не знаю никаких причин, почему кто-то захочет. Руководство говорит, что это может улучшить производительность, хотя.
Или ОС просто делает это автоматически
Это наверняка так. Вот почему они называют это "упреждающей" многозадачностью.
Смотря почему и как у вас "простой". Любой вызов блокирующей функции ввода-вывода, ожидание мьютекса или спящий режим автоматически отменит ваш поток и позволит ОС продолжить работу с чем-то другим. Только что-то вроде занятого цикла будет проблемой, но это не должно появляться в вашем дизайне в любом случае.
Ваша программа должна иметь только один центральный "бесконечный цикл". Если есть вероятность, что тело цикла "не работает", то было бы лучше, если бы вы могли заставить цикл выполнять одну из перечисленных выше системных функций, которая бы автоматически отображала всю привлекательность. Например, если ваш центральный цикл является epoll_wait
и все ваши операции ввода-вывода, таймеры и сигналы обрабатываются epoll, вызовите функцию с таймаутом -1
усыплять, если нечего делать. (Напротив, вызывая его с таймаутом 0
сделал бы это занятым шлейфом - плохо!).
Другие ответы IMO вдавались в детали. Простая вещь, которую нужно сделать, это:
while (1){
if (iHaveWorkToDo()){
doWork();
} else {
sleep(amountOfTimeToWaitBeforeNextCheck);
}
}
Примечание: это простое решение, которое полезно в однопоточном приложении или, например, в вашем случае, когда вам нечего делать в течение определенного периода времени; просто чтобы получить что-то достойное, работающее. Другая вещь в этом заключается в том, что sleep будет вызывать любую функцию yield, которую предпочитает os, так что в этом смысле это лучше, чем специфичный для os вызов yield.
Если вы хотите добиться высокой производительности, вам следует ждать событий.
Если у вас есть свои собственные события, это будет примерно так:
Lock *l;
ConditionVariable *cv;
while (1){
l->acquire();
if (iHaveWorkToDo()){
doWork();
} else {
cv->wait(lock);
}
l->release();
}
В ситуации сетевого типа это будет больше похоже на:
while (1){
int result = select(fd_max+1, ¤tSocketSet, NULL, NULL, NULL);
process_result();
}