1
我正在試驗一些抖動時序測試,方法是切換GPIO線並觀察示波器上的波形。我的內核編譯爲PREEMPT_RT
。我希望將進程的調度程序更改爲SCHED_FIFO
可以減少抖動,但似乎沒有太大區別。代碼如下。有沒有什麼我做錯了試圖從這個代碼獲得實時性能?使用SCHED_FIFO在Linux上看到糟糕的實時性能使用SCHED_FIFO
// Program to test Linux timing jitter by driving GPIO output via sysfs interface.
// In this variant, the scheduler is changed to SCHED_FIFO.
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
int main() {
char buf[128];
struct sched_param schedp;
const int pin = GPIO_TO_PIN(1, 24);
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open export for writing!\n");
return(-1);
}
int bytes_written = snprintf(buf, sizeof buf, "%d", pin);
write(fd, buf, bytes_written);
close(fd);
snprintf(buf, sizeof buf, "/sys/class/gpio/gpio%d/direction", pin);
fd = open(buf, O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open gpio direction for writing!\n");
return(-1);
}
if (write(fd, "out", 3) == -1) {
fprintf(stderr, "Failed to set direction!\n");
return(-1);
}
snprintf(buf, sizeof buf, "/sys/class/gpio/gpio%d/value", pin);
fd = open(buf, O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open gpio value for writing!\n");
return(-1);
}
// Change scheduler to SCHED_FIFO.
schedp.sched_priority = 99;
if (sched_setscheduler(0, SCHED_FIFO, &schedp)) {
perror("sched_setscheduler");
}
while (1) {
if (write(fd, "1", 1) != 1) {
fprintf(stderr, "Failed to write value!\n");
return(-1);
}
usleep(500);
if (write(fd, "0", 1) != 1) {
fprintf(stderr, "Failed to write value!\n");
return(-1);
}
usleep(500);
}
close(fd);
return 0;
}
一般來說,是的,期望用戶模式代碼的RT性能是錯誤的。你期望有多少抖動,你看到了多少? –
當系統空閒時,我發現方波中存在10%左右的抖動,但如果我運行命令,則有時會看到它不會在幾毫秒內切換。我認爲PREEMPT_RT新增點的目的是讓你可以在用戶空間中做實時代碼? – user43995
@ user43995有點。 Linux不是一個實時操作系統,所以仍然沒有保證。另外,默認情況下,5%的秒數仍可以被優先級較低的任務使用,並搶佔您的「實時」任務(請參閱https://www.kernel.org/doc/Documentation/scheduler/sched-rt-group。文本)。你也會受內核標記速率的限制,儘管通常的1000Hz標記速率可能只有1ms。 – nos