Q1: “It” is wake_up
. It wakes up all tasks that are waiting for the disk data. If they weren't waiting for that data, they wouldn't be waiting on that queue.
Q2: I'm not sure I understand the question. Each wake queue entry contains a pointer to the task. try_to_wake_up
receives a pointer to the task that it's supposed to wake up. It is called once per function.
Q3: There are lots of wait queues. There's one for every event that can happen. The disk driver sets up a wait queue for each request to the disk. For example, when the filesystem driver wants the content of a certain disk block, it asks the disk driver for that block, and then the request starts with the task that made the filesystem request. Other entries may be added to the wait queue if another request for the same block comes in while this one is still outstanding.
When an interrupt happens, the disk driver determines which disk has data available from the information passed by the hardware and looks up the data structure that contains the kernel data for this disk to find which request was to be filled. In this data structure, among others, are the location where the data is to be written and the corresponding wake queue indicating what to do next.
Q4: The process makes a system call, let's say to read a file. This triggers some code in the filesystem driver which determines that the data needs to be loaded from the disk. That code makes a request to the disk driver and adds the calling process to the request's wait queue. (There are actually more layers than that, but you get the idea.) When the disk read completes, the wait queue event triggers, and the process is thus removed from the disk's wait queue. The code triggered by the wait queue event is a function supplied by the filesystem driver, which copies the data to the process's memory and causes the read
system call to return.
The keypress generates an interrupt, just like you figured out. The interrupt is processed by an interrupt handler; which handler depends on the type of hardware, e.g. USB keyboard or PS/2 keyboard. The interrupt handler reads the key code from the hardware and buffers it. From the buffer the character is picked up by the tty driver, which, in the case of Ctrl-C recognizes it as the interrupt character and sends a SIGINT
to the foreground process group of the terminal. See n_tty.c.
Note that the tty driver is only involved in "terminal"-type (command line) interfaces, like the Linux console, serial terminals (/dev/ttyS*
), and pseudo ttys. GUI systems (X11, Wayland implementations) handle input devices differently.
Best Answer
The Linux timer interrupt handler doesn’t do all that much directly. For x86, you’ll find the default PIT/HPET timer interrupt handler in
arch/x86/kernel/time.c
:This calls the event handler for global clock events,
tick_handler_periodic
by default, which updates the jiffies counter, calculates the global load, and updates a few other places where time is tracked.As a side-effect of an interrupt occurring,
__schedule
might end up being called, so a timer interrupt can also lead to a task switch (like any other interrupt).Changing CONFIG_HZ changes the timer interrupt’s periodicity. Increasing
HZ
means that it fires more often, so there’s more timer-related overhead, but less opportunity for task scheduling to wait for a while (so interactivity is improved); decreasingHZ
means that it fires less often, so there’s less timer-related overhead, but a higher risk that tasks will wait to be scheduled (so throughput is improved at the expense of interactive responsiveness). As always, the best compromise depends on your specific workload. NowadaysCONFIG_HZ
is less relevant for scheduling aspects anyway; see How to change the length of time-slices used by the Linux CPU scheduler?See also How is an Interrupt handled in Linux?