Professional Documents
Culture Documents
Kernel Chintech Notes3
Kernel Chintech Notes3
Kernel Chintech Notes3
NZ
LK - Main Algorithms
chintech
SIGNALS
A signal is a short message that may be sent to a process or a group of processes. it is one of the oldest methods of Inter process communication. Represented in the system by a name of the form SIGXXXX. Egs SIGKILL,SIGSTOP,SIGCONT signals serve two main purpose. to make a process aware that a specific event has occurred.
NZ
to force a process to execute a signal handler function included in its code. LK - Main Algorithms
chintech
SIGNALS
the kernel uses signals to inform processes about certain events. the user uses signals to abort processes or to switch interactive programs to a defined state. the processes use signals to synchronize themselves with other processes.
NZ
LK - Main Algorithms
chintech
SIGNALS
the kernel can send signal to every other process. normal processes can send signals to other processes provided
it has proper capabilities. the destination process has the same UID and GUID. the signal is SIGCONT and destination process is in the same login session of the sending process.
LK - Main Algorithms chintech 4
NZ
SIGNALS
Explicitly ignore the signal. Execute the default action associated with the signal. This action which is predefined by the kernel depends upon the signal type. Catch the signal by invoking a corresponding signalhandler function.
The SIGKILL and SIGSTOP signals cannot be ignored, caught or blocked and their default actions must always be executed.
LK - Main Algorithms chintech
NZ
SIGNALS
Signals are sent via the function, int send_sig_info(int sig, struct siginfo *info, struct task_struct *t); where sig is the signal number, info refers to information about the sender process;if info =1, then signal is sent by a user mode process, if info=0, it is sent by the kernel; t is a pointer to the destination process. this function actually sets two components in the task_struct of the destination process
pending contains info about the signals that are received, the sender of the signal etc
chintech sigpendingLK set whenever a signal is handed over to a 6 - Main Algorithms
NZ
SIGNALS
Signals that have been generated but not been delivered are called pending signals. At any time, only one pending signal of a given type may exist for a process, additional pending signals of the same type to the same process are discarded. The blocked component in task_struct contains a bitmask of signals that have been blocked by a process. A blocked signal cannot be delivered to a process until it is unblocked.
LK - Main Algorithms chintech
NZ
SIGNALS
Signals can only be sent to the current process. So if a process is currently not executing, any signals sent to that process will be saved by the kernel until that process resumes execution. Signals of a given type may be blocked by a process. In this case, process will not receive a signal until it removes the block. When a process executes a signal handler function, it usually masks the corresponding signals ie it automatically blocks the signal until LK - Main Algorithms 8 chintech the handler terminates.
NZ
SIGNALS
Delivering a Signal
Kernel checks the sigpending flag of task structure for pending signals every time it completes handling an interupt or a system call. if sigpending is set and signal is not blocked, kernel invokes the do_signal() which takes over the actual signal handling. do_signal() will refer to the component sig in task_struct which holds information about how LK Main Algorithms 9 each process- handles every possible signal chintech
NZ
SIGNALS
Amongst other things it contains either the address of a routine which will handle the signal or a flag which tells Linux that the process either wishes to ignore this signal or let the kernel handle the signal for it. if the signal is caught, then a user-defined function has to be called, do_signal() calls the function handle_signal().
NZ
LK - Main Algorithms
chintech
10
Hardware Interrupts
Interrupts are used to allow the hardware to communicate with the operating system. Interrupts can occur at any time, when the kernel may want to finish something else it was trying to do. The kernels goal is therefore to get the interrupt out of the way as soon as possible and defer as much processing as it can.
NZ LK - Main Algorithms chintech 11
Hardware Interrupts
Suppose a block of data has appeared on a network line, when the hardware interrupts the kernel, it could mark the presence of data, give the processor back to whatever was running before, and do the rest of the processing later. The activities that the kernel needs to perform are divided into two parts: a top half that the kernel executes right away and a bottom half that is left for later. The kernel keeps a queue pointing to all the functions that represent bottom halves waiting to be executed and pulls them off the queue to LK - Main Algorithms 12 chintech execute them at particular points in processing.
NZ
Hardware Interrupts
Bottom half is implemented using softirqs, tasklets or bottom halves.
NZ
LK - Main Algorithms
chintech
13
The main handling routine for hardware interrupts is carried out by do_IRQ() Unsigned int do_IRQ(struct pt_regs regs) { int irq; struct irqaction *action; /*take irq number from the register*/ irq = regs.orig_eax & 0xff; /*find the respective handler*/ action = irq_desc[irq].action /* and execute the actions*/
NZ chintech 14
LK - Main Algorithms
while ( action ){ action->handler(irq, regs); action = action->next; } /* the actual hardware interrupt is exited here */ if (softirq_active & softirq_mask) do_softirq(); }
NZ
LK - Main Algorithms
chintech
15
Software Interrupts
Whenever a system call is about to return to userspace, or a hardware interrupt handler exits, any `software interrupts' which are marked pending (usually by hardware interrupts) are run. Much of the real interrupt handling work is done here. Tasklets, softirqs and bottom halves all fall into the category of `software interrupts'.
NZ
LK - Main Algorithms
chintech
16
Software Interrupts
Early in the transition to SMP, there were only `bottom halves' (BHs), which didn't take advantage of multiple CPUs. . No matter how many CPUs you have, no two BHs will run at the same time. This affects the performance. Softirqs are fully-SMP versions of BHs: they can run on as many CPUs at once as required. tasklets are like softirqs, except that any tasklet will only run on one CPU at any time, although different tasklets can run simultaneously (unlike different BHs).
NZ LK - Main Algorithms chintech 17
Software Interrupts
Softirq
Linux 2.4 uses a limited number of softirqs. There are only four kinds of softirqs
enum{HI_SOFTIRQ=0//(index0,handles highprioritytaskletsandbottomhalves) NET_TX_SOFTIRQ//(index=1,transmits packetstonetworkcards) NET_RX_SOFTIRQ//(index=2,receives packetsfromnetworkcards) TASKLET_SOFTIRQ//(index=3,handles tasklets). }
NZ LK - Main Algorithms chintech 18
Software Interrupts
The main data structure used to represent softirqs is the softirq_vec array which includes 32 elements of type softirq_action. Static struct softirq_action softirq_vec[32]; The registration(initialization) of an interrupt handler is carried out by the function open_softirq(). It uses 3 parameters: the softirq index , a pointer to the function to be executed, and a second pointer to the data structure that may be required by softirq function. softirqs are activated by invoking raise_softirq() , which takes one parameter ,the software index. do_softirq() executes the softirq functions.
NZ
LK - Main Algorithms
chintech
19
Void open_softirq(int nr, void (*action)(struct softirq_action*), void *data); Raise_softirq(int nr); Void do_softirq();
NZ
LK - Main Algorithms
chintech
20
Software Interrupts
Tasklets
Differ from softirqs because a tasklet cannot be executed by two CPUs at the same time. Different tasklets can be executed concurrently on several CPUs. The registration of a tasklet is carried out via the functin tasklet_init(). Using tasklet_schedule() a tasklet is marked for processing and the software interrupt TASKLET_SOFTIRQ is activated.
NZ
LK - Main Algorithms
chintech
21
/*Suppose you are writing a device driver and you want to use a tasklet; first you should allocate a new tasklet_struct data structure */ Struct tasklet_struct *t; /*initialize the tasklet by invoking tasklet_init(); this function takes 3 parameters; the address of the tasklet descriptor, the adress of your tasklet function and its optional integer argument*/ Void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); /*Activate the tasklet by calling the tasklet_schedule()*/ Void tasklet_schedule(struct tasklet_struct *t);
NZ
LK - Main Algorithms
chintech
22
Software Interrupts
Bottom halves
Software interrupts and tasklets are new in Linux 2.4, whereas bottom halves have been available for a very long time. Bottom halves are globally serialized ie, when one bottom half is in execution, the other CPUs cannot execute any bottom half, even if it is of different type. This degrades the performance of Linux Kernel on multiprocesor systems.
NZ
LK - Main Algorithms
chintech
23
then initiates a jump to the start address of the 32-bit code of the actual operating system kernel and continues from startup_32: in the file arch/i386/kernel/head.S More sections of the hardware are initialized here(the MMU, the coprocessor, etc) sets up the environment required for the execution of the first Linux process. sets up the environment required for the execution of the kernels C functions
NZ LK - Main Algorithms chintech
25
27
Now an attempt is made to establish a connection with the console and open the file descriptors 0, 1 and 2.
If (open(/dev/console, 0_RDWR, 0) printk(Warning: Unable to open an initial console.\n);
Then an attempt is made to execute a boot program specified by the user or one of the NZ LK - Main Algorithms chintech programs /sbin/init, /etc/init or /bin/init
28
NZ
LK - Main Algorithms
chintech
30
Timer Interrupts
Important global variables
jiffies
kernel/sched.c: unsigned long volatile jiffies=0; ticks (10ms) since the system was started up
xtime
kernel/sched.c : volatile struct timeval xtime; actual time
Timer Interrupts
Void do_timer (struct pt_regs *regs) { /*updates jiffies which contains the no. of elapsed ticks since the system started.*/ (*(unsigned long *)&jiffies)++ /*checks how long the current process has been running. update_process_times(user_mode(regs))*/ /*activates the TIMER_BH bottom half routine */ mark_bh(TIMER_BH) if (TQ_ACTIVE(tq_timer)) mark_bh(TQUEUE_BH) } NZ LK - Main Algorithms chintech 32
Timer Interrupts
Each invocation of the top half of the timer interrupt handler marks the TIMER_BH bottom half as active. As soon as the kernel leaves the interrupt mode, the timer_bh(), which is associated with TIMER_BH starts.
void timer_bh(void) { //updates the system date and time and computes the system load update_times(); //checks whether timers have expired. run_timer_list(); } NZ LK - Main Algorithms chintech 33
Timer Interrupts
The update_times() is responsible for updating the times.
Static inline void update_times(void) { unsigned long ticks; /*wall_jiffies stores the time of the last update of the xtime variable*/ ticks = jiffies wall_jiffies; if (ticks) { wall_jiffies += ticks update_wall_time(ticks); /* deals with the update of the real-time xtime and is called when some time has passes since the last call of the function.*/ } Calc_load(ticks);/* counts the no. of processes in the TASK_RUNNING or TASK_UNINTERRUPTIBLE state and uses this no. to updata CPU usage statistics*/ NZ } LK - Main Algorithms 34 chintech
Timer Interrupts
The function update_process_time collects data for the scheduler and decides whether it has to be called.
update_one_process(p, ticks, user, system, 0) struct task_struct *p = current; If(p->pid) { p->counter -= 1; if (p->counter <= 0) { p->counter = 0; p->need_resched = 1; } LK - Main Algorithms
NZ
chintech
35
Timer Interrupts
The if condition checks whether the kernel is executing process with PID 0, ie the swapper process. This is an idle process which runs whenever there are no other processes in the TASK_RUNNING state. For any other process, the counter component of the task structure is updated. When counter is zero, the time slice of the current process has expired and the scheduler is activated.
NZ
LK - Main Algorithms
chintech
36
Timer Interrupts
Under Linux, it is possible to limit a processs CPU consumption resource. This is done by the system call setrlimit. Exceeding the time limit is checked in the timer interrupt, and the process is either informed via the SIGXPU signal or aborted by means of SIGKILL signal. Subsequently the interval timers of the current task must be updated. When these have expired, the task is informed by a corresponding signal.
NZ
LK - Main Algorithms
chintech
37
Void update_one_process(p,user,system,cpu) *invoked by update_process times.*/ { p->per_cpu_utime[cpu] += user; p->per_cpu_stime[cpu] += system; do_process_times(p, user, system); do_it_virt(p, user) do_it_prof(p); } Void do_process_times(p, user, system) { psecs = (p ->times.tms_utime += user);
NZ
chintech
38
If (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur { if (!(psecs % HZ)) send_sig(SIGXCPU, p, 1); If (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_max send_sig(SIGKILL, p, 1); } }
NZ
LK - Main Algorithms
chintech
39
Void do_it_virt(p, user) { unsigned long it_virt = p->it_virt_value; if (it_virt) { it_virt -= user; if (it_virt <= 0) { it_virt = p->it_virt_incr; send_sig(SIGVTALRM, p, 1); } p->it_virt_value = it_virt user; }
NZ } LK - Main Algorithms chintech 40
The scheduler
The scheduler is responsible for allocating the processor to individual processes. The main variables in task_struct related to scheduling are :
policy : This is the scheduling policy that will be applied to this process. There are two types of Linux process, normal and real time. Real time processes have a higher priority than all of the other processes. If there is a real time process ready to run, it will always run first. Real time processes may have two types of policy, round robin and first in first out. In round robin scheduling, each runnable real time process is run in turn and in first in, first out scheduling each runnable process is run in the order that it is in on the run queue and that order is never changed. NZ LK - Main Algorithms chintech 41
The scheduler
Priority : This is the priority that the scheduler will give to this process. It is the value used for recalculation when all runnable processes have a counter value of 0. You can alter the priority of a process by means of system calls and the renice command rt_priority: Linux supports real time processes and these are scheduled to have a higher priority than all of the other non-real time processes in system. This field allows the scheduler to give each real time process a relative priority. The priority of a real time processes can be altered using system calls.
NZ LK - Main Algorithms chintech 42
The scheduler
Counter: This is the amount of time (in jiffies) that this process is allowed to run for. It is set to priority when the process is first run and is decremented each clock tick. The Linux scheduling algorithm is implemented in schedule() (kernel/sched.c). The scheduler is run from several places within the kernel.
There are system calls which call the schedule(), usually indirectly by calling sleep_on(). It may also be run at the end of a system call, just before a process is returned to user mode from system mode. The flag need_resched is checked by the ret_from_sys_call() routine. If it is set, the scheduler is called. One reason that it might need to run is because the system timer has just set LK - Main Algorithms 43 chintech the current processes counter to zero.
NZ
The scheduler
Each time the scheduler is run it does the following:
The scheduler runs the bottom half handlers and processes the scheduler task queue. The process with highest priority is determined. The new process becomes the current process.
NZ
LK - Main Algorithms
chintech
44
The scheduler
Simplified version of the schedule() :
asmlinkage void schedule(void) { struct task_struct * prev, * next, *p; prev = current; prev->need_resched = 0;
NZ
LK - Main Algorithms
chintech
45
The scheduler
The software interrupts are processed ie any bottom half handlers are processed now as it may manipulate information capable of influencing scheduling.
if (softirq_active(this_cpu) & softirq_mask(this_cpu)) do_softirq();
NZ
LK - Main Algorithms
chintech
46
The scheduler
If schedule() was called because the current process has to wait for an event, it is removed from the run queue. If the scheduling policy of the current processes is round robin then it is put onto the back of the run queue.
if (!prev->counter && prev->policy == SCHED_RR) { prev->counter = prev->priority; mov_last_runqueue(prev); } if ( prev->state != TASK_RUNNING ) { del_from_runqueue(prev); }
NZ
LK - Main Algorithms
chintech
47
The scheduler
Next the scheduler looks through the processes on the run queue looking for the most deserving process to run. If there are any real time processes (those with a real time scheduling policy) then those will get a higher weighting than ordinary processes. The function goodness() calculates the priority for each process.
NZ
LK - Main Algorithms
chintech
48
}
LK - Main Algorithms
chintech
49
The scheduler
If next_p is greater than zero, we have found a suitable candidate. If next_p is less than zero, there is no ready to run process and we must activate the idle task. In both cases next points to the task to be activated next. If next_p is equal to zero, there are ready to run processes, but we must recalculate their dynamic priorities ( value of counter). The counter values of all processes are recalculate. Then the scheduler is restarted.
NZ LK - Main Algorithms chintech 50
If (next_p == 0) { for_each_task(p) { p->counter = (p->counter / 2) + p->priority; } } The task indicated by next is the next to be activated. If( prev != next ) switch_to(prev,next);
NZ
}/* schedule() */
LK - Main Algorithms
chintech
51