Linux-Specific Non-Realtime Policies
The Linux 2.6 kernel series introduced two additional scheduling policies that do not exist in POSIX: SCHED_BATCH and SCHED_IDLE. These are set using the same POSIX realtime scheduling API (sched_setscheduler()), but they are not realtime policies. They are extensions of SCHED_OTHER for special use cases.
#ifdef SCHED_BATCH guards when writing portable code.SCHED_BATCH (Added in Linux 2.6.16)
SCHED_BATCH is designed for batch-style or CPU-intensive non-interactive jobs — programs that run for a long time, consume lots of CPU, and do not need to respond to user input or events quickly.
How It Differs from SCHED_OTHER
SCHED_BATCH is similar to SCHED_OTHER but with one behavioral difference: processes that frequently wake up are scheduled less aggressively. The scheduler assumes that a SCHED_BATCH process that wakes up is not trying to be interactive — it just needs to crunch numbers. This prevents SCHED_BATCH processes from “gaming” the scheduler by doing many short sleeps and wakes to appear interactive.
- Normal interactive processes
- Frequent wake-ups treated as interactive signals
- Scheduler gives waking process a boost
- Good for shells, editors, GUI apps
- CPU-bound non-interactive jobs
- Frequent wake-ups do NOT get boost
- Scheduler assumes CPU-hungry behavior
- Good for compilers, video encoders, simulations
When to Use SCHED_BATCH
Use SCHED_BATCH when you have a job that:
- Will run for a long time (minutes to hours)
- Does not interact with the user
- Should not interfere with interactive applications
- Examples:
make -j8(parallel build), FFmpeg video encoding, scientific simulations, backups
sched_priority field must be set to 0 (same as SCHED_OTHER). The nice value still applies and can be used to further adjust relative priority within SCHED_BATCH.SCHED_IDLE (Added in Linux 2.6.23)
SCHED_IDLE is the lowest-possible scheduling policy in Linux. A process running under SCHED_IDLE will only receive CPU time when no other process on the system wants to run. It is designed for truly background, opportunistic work that should never get in the way of anything else.
Key Properties
sched_setscheduler() with SCHED_IDLE.When to Use SCHED_IDLE
Use SCHED_IDLE for processes that should only run during genuine idle time:
- Background indexers (like file system indexing services)
- Screen savers doing computation
- Low-priority data analysis running “whenever possible”
- Any task where latency does not matter at all
Complete Scheduling Priority Hierarchy
All Linux Scheduling Policies: Summary Table
| Policy | POSIX? | Realtime? | sched_priority | Kernel Added | Best For |
|---|---|---|---|---|---|
| SCHED_OTHER | ✓ | ✗ | 0 | Always | Normal processes |
| SCHED_FIFO | ✓ | ✓ | 1–99 | Always | Critical RT tasks |
| SCHED_RR | ✓ | ✓ | 1–99 | Always | Shared RT workloads |
| SCHED_BATCH | ✗ | ✗ | 0 | 2.6.16 | CPU-bound batch jobs |
| SCHED_IDLE | ✗ | ✗ | 0 | 2.6.23 | True background work |
💻 Code Example 1: Set Process to SCHED_BATCH
/* set_batch.c
* Switches the calling process to SCHED_BATCH scheduling.
* Suitable for CPU-intensive background jobs.
*
* Compile: gcc set_batch.c -o set_batch
* Run: ./set_batch
*
* Note: SCHED_BATCH can be set without root privileges
* (it does not increase priority above SCHED_OTHER).
*/
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <unistd.h>
#ifndef SCHED_BATCH
#define SCHED_BATCH 3 /* Linux-specific; define fallback */
#endif
int main(void)
{
struct sched_param sp;
int policy;
/* SCHED_BATCH requires sched_priority = 0 */
sp.sched_priority = 0;
printf("Setting scheduling policy to SCHED_BATCH...\n");
if (sched_setscheduler(0, SCHED_BATCH, &sp) == -1) {
perror("sched_setscheduler(SCHED_BATCH)");
exit(EXIT_FAILURE);
}
/* Verify */
policy = sched_getscheduler(0);
if (policy == -1) {
perror("sched_getscheduler");
exit(EXIT_FAILURE);
}
printf("Current policy: %s\n",
(policy == SCHED_BATCH) ? "SCHED_BATCH" : "OTHER");
/*
* Now run the CPU-intensive batch work here.
* This process will be de-prioritized compared to SCHED_OTHER
* processes that need to run interactively.
*/
printf("Running batch work (simulated)...\n");
volatile long long x = 0;
for (long long i = 0; i < 100000000LL; i++)
x += i; /* CPU-bound busy loop */
printf("Batch work done. Result: %lld\n", x);
return EXIT_SUCCESS;
}
💻 Code Example 2: Set Process to SCHED_IDLE
/* set_idle.c
* Switches the calling process to SCHED_IDLE — the lowest
* possible scheduling policy. The process only runs when
* no other process on the system wants CPU time.
*
* Compile: gcc set_idle.c -o set_idle
* Run: ./set_idle
*
* Note: SCHED_IDLE can be set without root on most kernels.
* Once set, the process CANNOT change its own policy
* regardless of RLIMIT_RTPRIO.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <unistd.h>
#ifndef SCHED_IDLE
#define SCHED_IDLE 5 /* Linux-specific fallback */
#endif
const char *policy_to_str(int p) {
if (p == SCHED_OTHER) return "SCHED_OTHER";
if (p == SCHED_BATCH) return "SCHED_BATCH";
if (p == SCHED_IDLE) return "SCHED_IDLE";
if (p == SCHED_FIFO) return "SCHED_FIFO";
if (p == SCHED_RR) return "SCHED_RR";
return "UNKNOWN";
}
int main(void)
{
struct sched_param sp;
int before, after;
/* Show current policy */
before = sched_getscheduler(0);
printf("Before: %s\n", policy_to_str(before));
/* SCHED_IDLE requires sched_priority = 0 */
sp.sched_priority = 0;
if (sched_setscheduler(0, SCHED_IDLE, &sp) == -1) {
perror("sched_setscheduler(SCHED_IDLE)");
exit(EXIT_FAILURE);
}
after = sched_getscheduler(0);
printf("After: %s\n", policy_to_str(after));
/*
* WARNING: Once we are SCHED_IDLE, we CANNOT change our
* own policy back (unless we are root or have RLIMIT_RTPRIO).
* The SCHED_IDLE policy ignores RLIMIT_RTPRIO for self-changes.
*
* Attempting to change back to SCHED_OTHER will fail:
*/
sp.sched_priority = 0;
if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
perror("Can't change from SCHED_IDLE (as expected)");
} else {
printf("Changed back to SCHED_OTHER (you have root)\n");
}
printf("Running idle-priority background work...\n");
/* This process will only use CPU when system is idle */
for (int i = 0; i < 5; i++) {
sleep(1);
printf(" Idle work tick %d\n", i+1);
}
return EXIT_SUCCESS;
}
🎯 Interview Questions
#ifdef SCHED_BATCH and #ifdef SCHED_IDLE guards.sched_priority = 0. Any other value will cause sched_setscheduler() to fail. The nice value still has meaning for SCHED_BATCH but is ignored for SCHED_IDLE.