Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

The Linux Kernel/Multitasking

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

multitaskingexecutionthreads or taskssynchronizationSchedulerinterrupts coreCPU specific Linux kernel is a preemptive Computer multitasking multitasking operating system. As a multitasking OS, it allows multiple processes to share processors (CPUs) and other system resources. Each CPU executes a single task at a time. However, multitasking allows each processor to switch between tasks that are being executed without having to wait for each task to finish. For that, the kernel can, at any time, temporarily interrupt a task being carried out by the processor, and replace it by another task that can be new or a previously suspended one. The operation involving the swapping of the running task is called context switch. Execution ⚲ API ↪ ⚙️ implementations 2 execve ↪ do_execveat_common runs an executable file in the context of current process, replacing the previous executable. This system call is used by family of functions of libc 3 exec. The Executable and Linkable Format ELF binary format is loaded by fs/binfmt_elf.c. 2 clone. Clone creates a child process that may share parts of its execution context with the parent. It is often used to implement threads (though programmers will typically use a higher-level interface such as 7 pthreads, implemented on top of clone). 2 wait ↪ kernel_waitid suspends the execution of the calling process until one of its child processes terminates. Syscall 2 getpid ↪ task_tgid_vnr returns PID of the current process which internally is called TGID - thread group id. A process can contain many threads. 2 gettid ↪ task_pid_vnr returns thread id. Which internally is historically called PID. ⚠️ Warning: confusion. User space PID ≠ kernel space PID. 1 ps -AF lists current processes and thread as Light-weight process LWP. For a single thread process all these IDs are equal. High-resolution delays: 2 nanosleep ↪ sys_nanosleep hrtimer_nanosleep 2 clock_nanosleep ↪ sys_clock_nanosleep Wait for a signal: 2 pause ↪ sys_pause 2 sigsuspend ↪ sys_sigsuspend 🔨 stress-ng --context, --switch See Processes for process creation and termination. Inter-process communication Inter-process communication (IPC) refers specifically to the mechanisms an operating system provides to allow processes it manages to share data. Methods for achieving IPC are divided into categories which vary based on software requirements, such as performance and modularity requirements, and system circumstances. Linux inherited from Unix the following IPC mechanisms: Signals (⚲ API ↪ ⚙️ implementations): 2 kill sends signal to a process 2 tgkill ↪ do_tkill sends a signal to a thread 2 process_vm_readv ↪ process_vm_rw - zero-copy data transfer between process address spaces 2 sigaction ↪ do_sigaction – examine and change a signal action 2 sigprocmask – examine and change blocked signals 2 sigpending ↪ do_sigpending – examine pending signals 2 sigsuspend – wait for a signal 2 sigaltstack – set or get signal stack context 2 sigtimedwait ↪ do_sigtimedwait – synchronously wait for queued signals 7 signal – overview of signals linux/sched/signal.h – signal-related task accessors kernel/signal.c – signal delivery and handling 🔨 stress-ng --sigq Anonymous pipes and named pipes (FIFOs) 2 mknod ↪ do_mknodat S_IFIFO Express Data Path PF_XDP Unix domain socket PF_UNIX Memory-mapped files 2 mmap ⤑ ksys_mmap_pgoff 2 eventfd ↪ do_eventfd – event notification via file descriptor 2 signalfd ↪ do_signalfd4 – receive signals via file descriptor 2 timerfd_create – timer notification via file descriptor Sys V IPC: Message queues: 2 msgget, 2 msgsnd, 2 msgrcv ↪ ipc/msg.c Semaphores Shared memory: 2 shmget, 2 shmctl, 2 shmat, 2 shmdt ↪ ipc/shm.c POSIX message queues: 7 mq_overview, 3 mq_open, 3 mq_send, 3 mq_receive ↪ ipc/mqueue.c 🔨 --mq 📖 References Inter-process communication 7 sysvipc Threads or tasks In Linux kernel "thread" and "task" are almost synonyms. ⚲ API linux/sched.h - the main scheduler API task_struct arch/x86/include/asm/current.h – x86 current task pointer current and get_current () return current task_struct uapi/linux/taskstats.h per-task statistics linux/thread_info.h current_thread_info() returns thread_info linux/sched/task.h - interface between the scheduler and various task lifetime (fork()/exit()) functionality linux/kthread.h - simple interface for creating and stopping kernel threads without mess. kthread_run creates and wakes a thread kthread_create ⚙️ Internals kthread_run ↯ hierarchy: kernel/kthread.c – kernel thread creation and management kthreadd – parent kernel thread and the creator of all other kernel threads. Dequeues kthread_create_info from kthread_create_list. create_kthread kernel_thread kthread – invokes threadfn __kthread_create_on_node – enqueues kthread_create_info into kthread_create_list kernel/fork.c – process creation and cloning kernel_thread kernel_clone 🔨 stress-ng --clone, --fork, --pthread Scheduler The Scheduling_(computing)#Linux scheduler is the part of the operating system that decides which process runs at a certain point in time. It usually has the ability to pause a running process, move it to the back of the running queue and start a new process. Active processes are placed in an array called a run queue, or runqueue - rq. The run queue may contain priority values for each process, which will be used by the scheduler to determine which process to run next. To ensure each program has a fair share of resources, each one is run for some time period (quantum) before it is paused and placed back into the run queue. When a program is stopped to let another run, the program with the highest priority in the run queue is then allowed to execute. Processes are also removed from the run queue when they ask to sleep, are waiting on a resource to become available, or have been terminated. Since version 6.6 the Linux kernel uses the Earliest eligible virtual deadline first scheduling (EEVDF) algorithm, which replaced the Completely Fair Scheduler (CFS). While much of the CFS infrastructure remains: sched_entity, cfs_rq, the red-black tree, load balancing, and kernel/sched/fair.c — the task selection logic is fundamentally different. EEVDF is based on a classic scheduling algorithm originally designed for packet networks. The scheduler has a scheduling complexity of O(log N), where N is the number of tasks in the runqueue. Both picking and reinserting a task require O(log N) operations, because the run queue is implemented as a red–black tree. The runqueue (cfs_rq) is implemented as a red-black tree representing a "timeline" of future task execution. The scheduler uses nanosecond granularity accounting and requires no heuristics or interactivity estimators. EEVDF improves sleeper fairness over CFS by tracking lag (vlag) — the difference between the service a task was entitled to and the service it actually received. When a sleeping task wakes up, its lag determines eligibility, ensuring interactive tasks get prompt service without starving long-running tasks. The data structure used for the scheduling algorithm is a red-black tree in which the nodes are sched_entity structures, embedded in task_struct. With EEVDF, each task has a time slice (sysctl_sched_base_slice, default 0.7ms) that determines its request length. EEVDF computes a virtual deadline for each task: vd_i = ve_i + r_i/w_i, where ve_i is the eligible time, r_i is the request size, and w_i is the weight (determined by nice value). The scheduler picks the eligible task with the earliest virtual deadline via pick_eevdf. The Linux kernel contains different scheduler classes (or policies). The EEVDF scheduler handles SCHED_NORMAL (aka SCHED_OTHER). The kernel also contains two additional classes SCHED_BATCH and SCHED_IDLE, and another two real-time scheduling classes named SCHED_FIFO (realtime first-in-first-out) and SCHED_RR (realtime round-robin), with a third realtime scheduling policy known as SCHED_DEADLINE that implements the Earliest deadline first scheduling earliest deadline first algorithm (EDF) added later. Any realtime scheduler class takes precedence over any of the "normal" —i.e. non realtime— classes. The scheduler class is selected and configured through the 2 sched_setscheduler ↪ do_sched_setscheduler system call. Properly balancing latency, throughput, and fairness in schedulers is an open problem.Malte Skarupke. "Measuring Mutexes, Spinlocks and how Bad the Linux Scheduler Really is". ⚲ API 1 renice – priority of running processes 1 nice – run a program with modified scheduling priority 1 chrt – manipulate the real-time attributes of a process 2 sched_getattr ↪ sys_sched_getattr – get scheduling policy and attributes linux/sched.h – the main scheduler API schedule 2 getpriority, 2 setpriority 2 sched_setscheduler, 2 sched_getscheduler /sys/kernel/debug/sched/ – scheduler debugfs tuning directory features – toggle scheduler feature flags base_slice_ns – EEVDF base time slice (default 700000) migration_cost_ns – cost threshold for task migration between CPUs nr_migrate – max tasks to migrate per balancing pass debug – dump detailed scheduler state numa_balancing/ – NUMA balancing scan parameters ⚙️ Internals sched_init is called from start_kernel __schedule is the main scheduler function. runqueues, this_rq kernel/sched – scheduler subsystem kernel/sched/core.c – core scheduling logic kernel/sched/fair.c implements SCHED_NORMAL, SCHED_BATCH, SCHED_IDLE pick_eevdf – core of EEVDF sched_setscheduler, sched_getscheduler task_struct::rt_priority and other members with less unique identifiers 🔨 stress-ng --schedpolicy 🛠️ Utilities 1 pidstat 1 pcp-pidstat 1 perf-sched Understanding Scheduling Behavior with SchedViz 📖 References 7 sched Scheduling scheduler EEVDF Scheduler scheduler/sched-eevdf.html An EEVDF CPU scheduler for Linux LWN Delaying and scheduling routines driver-api/basics.html#delaying-and-scheduling-routines CFS Completely Fair Scheduler scheduler/sched-design-CFS.html CFS Bandwidth Control scheduler/sched-bwc.html CPU cgroup controller CPU cgroup interface files admin-guide/cgroup-v2.html#cpu-interface-files Completely fair scheduler LWN Tuning the task scheduler stop using CPU limits on Kubernetes Deadline Task Scheduler scheduler/sched-deadline.html kernel sched kernel/syscalls sched_setparam kernel/syscalls sched_getscheduler kernel/syscalls sched_setscheduler 📚 Further reading about the scheduler Tuning scheduling policy, RHEL Scheduler tracing bcc/ebpf CPU and scheduler tools Preemption Preemption refers to the ability of the system to interrupt a running task to switch to another task. This is essential for ensuring that high-priority tasks receive the necessary CPU time and for improving the system's responsiveness. In Linux, preemption models define how and when the kernel can preempt tasks. Different models offer varying trade-offs between system responsiveness and throughput. 📖 References Proper Locking Under a Preemptible Kernel locking/preempt-locking.html preempt_enable – decrement the preempt counter preempt_disable – increment the preempt counter preempt_enable_no_resched – decrement, but do not immediately preempt preempt_check_resched – if needed, reschedule preempt_count – return the preempt counter kernel/Kconfig.preempt – preemption model configuration CONFIG_PREEMPT_NONE – no forced preemption for servers CONFIG_PREEMPT_VOLUNTARY – voluntary preemption for desktops CONFIG_PREEMPT – preemptible except for critical sections for low-latency desktops CONFIG_PREEMPT_RT – real-time preemption for highly responsive applications CONFIG_PREEMPT_DYNAMIC – allows runtime switching of preemption model /sys/kernel/debug/sched/preempt – shows and controls the active preemption model sched_ext Since version 6.12 the kernel supports SCHED_EXT — an extensible scheduler class whose behavior is defined by a set of eBPF programs. Any scheduling algorithm can be implemented on top of sched_ext, loaded and unloaded dynamically at runtime. The system integrity is maintained no matter what the BPF scheduler does: the default scheduling behavior is restored on error or when a runnable task stalls. ⚙️ Internals CONFIG_SCHED_CLASS_EXT kernel/sched/ext.c – extensible BPF scheduler class sched_ext_ops – BPF scheduler operations sched_ext_entity – per-task sched_ext data, embedded in task_struct 👁 Examples tools/sched_ext – in-tree example BPF schedulers 📖 References Extensible Scheduler Class scheduler/sched-ext.html sched-ext/scx – production BPF schedulers Scheduler BPF LWN Energy Aware Scheduling 🚀 advanced topic Since version 5.0, Energy Aware Scheduling (EAS) gives the scheduler the ability to predict the impact of its decisions on the energy consumed by CPUs. EAS relies on an Energy Model (EM) to select an energy efficient CPU for each task, with minimal impact on throughput. EAS operates only on heterogeneous CPU topologies (such as ARM big.LITTLE) where the potential for energy savings is highest. ⚲ API /proc/sys/kernel/sched_energy_aware – enable or disable EAS linux/energy_model.h em_perf_domain – performance domain descriptor em_cpu_get – get the EM for a given CPU ⚙️ Internals CONFIG_ENERGY_MODEL find_energy_efficient_cpu – find most energy-efficient target CPU for a waking task kernel/power/energy_model.c – CPU energy model framework 📖 References Energy Aware Scheduling scheduler/sched-energy.html Energy Model of devices power/energy-model.html Wait queues A wait queue in the kernel is a data structure that allows one or more processes to wait (sleep) until something of interest happens. They are used throughout the kernel to wait for available memory, I/O completion, message arrival, and many other things. In the early days of Linux, a wait queue was a simple list of waiting processes, but various scalability problems (including the thundering herd problem) have led to the addition of a fair amount of complexity since then. ⚲ API linux/wait.h wait_queue_head consists of double linked list of wait_queue_entry and a spinlock. Waiting for simple events: Use one of two methods for wait_queue_head initialization: init_waitqueue_head initializes wait_queue_head in function context DECLARE_WAIT_QUEUE_HEAD - actually defines wait_queue_head in global context Wait alternatives: wait_event_interruptible - preferable wait wait_event_interruptible_timeout wait_event - uninterruptible wait. Can cause deadlock ⚠ wake_up etc 👁 For example usage see references to unique suspend_queue. Explicit use of add_wait_queue instead of simple wait_event for complex cases: DECLARE_WAITQUEUE actually defines wait_queue_entry with default_wake_function add_wait_queue inserts process in the first position of a wait queue remove_wait_queue ⚙️ Internals ___wait_event __add_wait_queue __wake_up_common, try_to_wake_up kernel/sched/wait.c – wait queue implementation Simple wait queues – simplified version with raw spinlock, suitable for RT and restricted contexts: linux/swait.h swait_queue_head, swait_queue kernel/sched/swait.c – simple wait queue implementation 📖 References Wait queues and Wake events driver-api/basics.html#wait-queues-and-wake-events Real-time Time ⚲ UAPI uapi/linux/time.h timespec – nanosecond resolution timeval – microsecond resolution timezone ... uapi/linux/time_types.h __kernel_timespec – nanosecond resolution, used in syscalls ... ⚲ API linux/delay.h – busy-wait delay functions for timing control linux/sched/clock.h sched_clock ... linux/time.h tm get_timespec64 ... linux/ktime.h ktime_t – nanosecond scalar representation for kernel time values ktime_sub ... linux/timekeeping.h ktime_get, ktime_get_ns ktime_get_real ... linux/time64.h timespec64 time64_t ns_to_timespec64 timespec64_sub ktime_to_timespec64 ... uapi/linux/rtc.h linux/jiffies.h ⚙️ Internals kernel/time – timekeeping, timers and clocks timekeeper – central timekeeping state tkr_mono – monotonic clock, frequency corrected by NTP for accurate real-world seconds 8 chronyd → 2 adjtimex ↪ sys_adjtimex tkr_raw – raw monotonic clock, no NTP correction, drifts with crystal error update_wall_time ← tick_periodic → timekeeping_advance (blocks readers with write_seqcount_begin): tk_clock_read – reads clocksource hardware logarithmic_accumulation – accumulates ticks in doubling steps (efficient for NO_HZ) timekeeping_adjust – corrects mult to steer toward NTP frequency accumulate_nsecs_to_secs – rolls nanoseconds into seconds timekeeping_update_from_shadow – publishes shadow timekeeper to live update_vsyscall – copies time data to vDSO page for userspace 2 clock_gettime without syscall update_fast_timekeeper – NMI-safe copy via write_seqcount_latch_begin (two copies, ktime_get_mono_fast_ns and other ktime_get*_fast readers spin on read_seqcount_latch_retry) ktime_get and all ktime_get* readers spin on read_seqcount_retry until consistent ktime_get = tkr_mono.base + timekeeping_get_ns timekeeping_get_ns → tk_clock_read, timekeeping_cycles_to_ns – converts cycles to ns (delta only, added to base by caller) tk_clock_read → arch_inlined_clocksource_read → rdtsc_ordered – x86 Time_Stamp_Counter TSC fast path via static key timekeeping_get_ns and rdtsc_ordered are safe to trace timekeeping (no seqcount), unlike ktime_get which would block on read_seqcount_retry 🔨 stress-ng --timer, --hrtimers Precision Time Protocol PTP provides sub-microsecond clock synchronization over a network using hardware timestamping. ⚲ API /sys/class/ptp/ – PTP hardware clock devices ptp4l – PTP boundary/ordinary clock daemon phc2sys – synchronize system clock to PTP hardware clock uapi/linux/ptp_clock.h ⚙️ Internals drivers/ptp – PTP hardware clock drivers 📖 References PTP hardware clock infrastructure for Linux driver-api/ptp.html ktime accessors core-api/timekeeping.html Clock sources, Clock events, sched_clock() and delay timers timers/timekeeping.html Time and timer routines driver-api/basics.html#time-and-timer-routines Year 2038 problem