Kernel Chintech Notes3

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 51

MAIN ALGORITHMS

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

Actions performed on delivering a signal

there are 3 ways in which a process can respond to a signal.


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

Why are signals pending?

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

Booting the system


Once LILO finds the Linux kernel and loads it into memory, execution starts at the entry point start: which is held in the arch/i386/boot/setup.S file. This section contains assembler code responsible for initializing the hardware. Once the essential hardware parameters have been established, the CPU is switched into protected mode by setting the protected mode bit in the machine status word.
NZ LK - Main Algorithms chintech 24

Booting the system


The assembler instruction
jmpi 0x100000 , __KERNEL_CS

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

Booting the system


Once initialization is complete, the first C function, start_kernel() from init/main.c is called. The start_kernel( ) function completes the initialization of the Linux kernel. Nearly every kernel component is initialized by this function; for eg.,
1. 2. 3. 4. 5. 6. 7. NZ Initialise irqs. Initialise data required for scheduler. Initialise time keeping data. Initialise softirq subsystem. Parse boot commandline options. Initialise page tables If module support was compiled into the kernel, initialise dynamical module loading facility. LK - Main Algorithms chintech 26

Booting the system


The Kernel Idle Thread (Process 0) generates a kernel thread for process 1(commonly called init process) which executes the init() which is one of the routines defined in linux/init/main.c. Kernel_thread (init,NULL,) After creating process 1, Process 0 is only concerned with using up unused computing time. it executes the cpu_idle() function and is selected by the scheduler only where there are no other processes in the TASK_RUNNING state. The init() carries out the remaining initialization. The do_basic_setup() initializes all drivers for the hardware NZ LK - Main Algorithms chintech here.

27

Booting the system


Static int init() { do_basic_setup();

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

Booting the system


These usually start the background process running under Linux and make sure that the getty program runs on each connected terminal thus a user can log on to the system. if (execute_command) execve(execute_command,argv_init,envp_init); execve(/sbin/init,argv_init,envp_init); execve(/etc/init,argv_init,envp_init); execve(/bin/init,argv_init,envp_init);
NZ LK - Main Algorithms chintech 29

Booting the system


If none of the programs mentioned above exists, an attempt is made to start a shell, so that the super user can repair the system. If this is not possible the system is stopped.
execve(/bin/sh,argv_init,envp_init); Panic(No init found);

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 interrupt routine (do_timer())


updates jiffies and make the bottom half active the bottom half is called later, an handles the rest of the work.
NZ LK - Main Algorithms chintech 31

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

psecs += (p->times.tms_stime += system);


LK - Main Algorithms

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

Next = idle_task; Next_p = -1000; List_for_each(p,&runqueue_head) { if( ! Can_schedule(p) ) continue;

/* next process */ /* and the priority*/

weight = goodness(p,prev,this_cpu); if( weight > next_p) { next_p = weight; next = p;


NZ

}
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

You might also like