Rozszerza on możliwości systemu Linux o rozdzielczość czasu rzędu 10 mikrosekund oraz scheduler czasu rzeczywistego.
KURT jest miękkim systemem czasu rzeczywistego. Oznacza to, że program szeregujący stara się zapewnić żądane czasy wykonania, ale niepowodzenie nie ma żadnych następstw.
/usr/src
:
cd /usr/src tar xjf linux-2.4.18.tar.bz2 cd linux cat ../preempt-kernel-rml-2.4.18-5.patch | patch -p1 cat ../lock-break-rml-2.4.18-1.patch | patch -p1 cat ../kurt-2.4.18-2.patch | patch -p1
make config make menuconfig make xconfigOpcje dotyczące KURT-Linux to:
make clean make dep make bzImagePo zainstalowaniu jądra i ponownym uruchomieniu komputera KURT-Linux jest gotowy do pracy.
tar xjf kurt-2.4.18-2.tar.bz2 cd kurt-2.4.18 ./configure make make installUwaga: Należy zmienić wartości zmiennych: KURT_LINUX, INSTALL_LIB, INSTALL_INCLUDE w pliku Makefile.include.
Następnie tworzymy odpowiednie urządzenia:
mknod /dev/kurt c 240 0 mknod /dev/utime c 241 0 mknod /dev/dstream c 242 0KURT-Linux jest już gotowy do pracy.
Dostęp do tego mechanizmu uzyskujemy za pomocą jednej z poniższych metod:
void nanosleep_test(int delay) { struct timespec sleepy; sleepy.tv_sec = 0; sleepy.tv_nsec = delay * 1000; nanosleep(&sleepy, 0); }
void timer_handler(int signal) { } void setitimer_test(int delay, int interval, int tries) { struct itimerval timer; sigset_t mask; struct sigaction action; int i; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = interval; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = delay; sigemptyset(&mask); action.sa_handler = timer_handler; action.sa_flags = 0; sigaction(SIGALRM, &action, 0); setitimer(ITIMER_REAL, &timer, 0); for (i = 0 ; i < tries ; i++) { sigsuspend(&mask); } timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 0; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &timer, 0); }
void select_test(int delay) { struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = delay; select(0, 0, 0, 0, &timeout); }
void poll_test(int delay) { poll(0, 0, delay); }
Użytkownik wysyła do jądra informację kiedy dany proces czasu rzeczywistego powinien się rozpocząć i kiedy zakończyć. Cała komunikacja z podsystemem KURT odbywa się przez pseudo-urządzenie ``/dev/kurt''.
Kernel modes | Process modes | |||||
---|---|---|---|---|---|---|
EPISODIC | CONTINUOUS | |||||
EXPLICIT | ANYTIME | PERIODIC | EXPLICIT | ANYTIME | PERIODIC | |
FOCUSSED | OK | - | - | OK | OK | - |
PREFFERED | OK | - | - | OK | OK | - |
MIXED | OK | - | OK | OK | Linux | - |
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <asm/timex.h> #include <linux/rt.h> void do_stuff(void) { struct timeval time; cycles_t tsc; static int i = 0; /* Just get the time and print it */ tsc = get_cycles(); gettimeofday(&time, NULL); printf("(%d)Time is %d.%06d (tsc = %Lu).\n", i++, (int)time.tv_sec, (int)time.tv_usec, tsc); } int main(int argc, char **argv) { int kurtdev; struct rtparams rt_param; if (argc != 2) { fprintf(stderr, "Usage : %s <rtid>\n", argv[0]); exit(1); } /* Open /dev/kurt */ kurtdev = kurt_open(); rt_param.rt_id = atoi(argv[1]); rt_param.period = 0; rt_param.exec_time = 300; rt_param.rt_mode = KURT_EXPLICIT | KURT_EPISODIC; rt_param.rt_name[0] = \0 ; set_rtparams(kurtdev, 0, RT_REGISTER, &rt_param); printf("Real-time process %u entering work loop... " "(terminate with CTRL-C)\n", rt_param.rt_id); /* Real-time work loop, exit by hitting CTRL-C */ while (1) { /* This will suspend the process before the first * wakeup, and between each following wakeup */ rt_suspend(kurtdev, SUSPEND_IF_NRT | START_SCHED); do_stuff(); } return 0; }
#include <stdio.h> #include <linux/timer.h> #include <linux/rt.h> int main(void) { FILE *sched_file; struct timer_list timer; int i, fd; /* Open binary schedule file */ sched_file = fopen("/tmp/simple_schedule.bin", "w"); fd = fileno(sched_file); timer.list.next = NULL; timer.list.prev = NULL; /* Send event to KURT s process module */ timer.data = KURT_PROCESS_MODULE; /* All events are wakeup timers */ timer.flags = KURT_WAKEUP; /* The schedule will not be longer than a jiffy, so expires * will remain at 0 for every timer. */ timer.expires = 0; for (i = 0; i < 10; i++) { /* Events are 500 microseconds apart */ timer.usec = i * 500; /* Send to real-time process 0 */ timer.function = 0; /* Write the event to file */ write(fd, &timer, sizeof(struct timer_list)); i++; timer.usec = i * 500; /* Send to real-time process 1 */ (unsigned long)timer.function = 1; /* Write the event to file */ write(fd, &timer, sizeof(struct timer_list)); } /* Write the repeat event (5ms schedule) */ timer.usec = 5000; timer.data = KURT_REPEAT; write(fd, &timer, sizeof(struct timer_list)); fclose(sched_file); exit(0); }