Unlike QNX the Linux kernel is open source software. Which means that you can modify and change it in whatever ways you desire. You grab the sources from http://kernel.org (preferrably you use Git to clone into a local repository), make your modifications, additions, etc. compile the think and boot your computer with it.
Note that Linux since version 2.6 also offers realtime scheduling, which might be sufficient.
Update code example
For the time raster task execution I suggest the following:
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 500
#include <sched.h> /* for sched_setsched */
#include <unistd.h> /* for usleep */
#include <time.h> /* for clock_gettime */
#include <string.h> /* for memset */
#define MS_to_US(x) ((x)*1000)
useconds_t delta_t_us(struct timespec const *a, struct timespec const *b)
{
time_t const delta_sec = b->tv_sec - a->tv_sec;
long const delta_nsec = b->tv_nsec - a->tv_nsec;
/* this might actually overflow for "long" time intervalls"
* should be safe for a delta_t < 2ms though */
return delta_sec * 1000000 + delta_nsec / 1000;
}
void rastertask()
{
struct sched_param sparm;
memset(&sparm, 0, sizeof(sparm));
sparm.sched_priority = 10; /* 0 = lowest, 99 = highest */
sched_setscheduler(
0 /* pid, 0 ==> this process */,
SCHED_RR /* policy */,
&sparm);
unsigned int n_loop;
for(n_loop=0;;n_loop++) {
struct timespec ts_start, ts_end;
clock_gettime(CLOCK_MONOTONIC, &ts_start);
TASK1(); /* gets called every 2ms */
if( (n_loop % 5) == 0) {
TASK2(); /* get called every 5 * 2ms = 10ms */
}
if( (n_loop % 50) == 0) {
TASK2(); /* get called every 50 * 2ms = 100ms */
}
if( (n_loop % 250) == 0 ) {
/* reset loop counter when smallest common
* multiple of timing grid has been reached */
n_loop = 0;
}
clock_gettime(CLOCK_MONOTONIC, &ts_end);
useconds_t const tasks_execution_time = delta_t_us(&ts_start, &ts_end);
if( tasks_execution_time >= MS_to_US(2) ) {
/* report an error that tasks took longer than 2ms to execute */
}
/* wait for 2ms - task_execution_time so that tasks get called in
* a close 2ms timing grid */
usleep( MS_to_US(2) - tasks_execution_time );
}
}
Please note that the process requires either CAP_SYS_NICE privileges (prior to Linux 2.6.12) or sufficient RLIMIT_RTPRIO resource limits to be able to set its priority.