Title: Essentials of the Detailed Design DD
1- Essentials of the Detailed Design (DD)
- Function Flow Chart (FFC)
- As a code block, functions (a.k.a. procedures,
routines, subroutines) are widely used in any
modern languages - Typically, a program consists of multiple
functions - Callers and callees
- FFC provides a static view for the program
steucture - Any DD must include FFC
2- How to read the source code
- linux-2.2.5 The complete distribution of the
version of the kernel code used in this book - lckc_code All of the code included in this book
in a single large file with the lines
numbered--exactly as it appears in the first part
of this book - You should mainly read file lckc_code
3- Example of the Function Flow Chart (the callees
of do_timer) - 27446 do_timer
- gtgt mark_bh
- gtgt set_bit
- gtgt user_mode
- To find all callees, you use find in the
lckc_code file to seek all function names called
inside do_timer
4- Example of the Function Flow Chart (the callers
of do_timer) - 27446 do_timer
- ltlt do_timer_interrupt
- ltlt timer_interrupt
- To find all callers, you use find in the
lckc_code file to seek all function that call
do_timer
5- System Calls
- Kernel Space and User Space
- Basics of System Calls
- A (true) system call occurs when a process asks
a service provided by the kernel - The process itself is then be put on hold
- The kernel does the work
- The process is then restarted
- The main categories involve accessing resources
6- process (fork, execve, kill)
- time (settimeofsay, time)
- I/O (open, close, read, write)
- memory (mmap, brk)
- The return values
- A system call must return long or int
- e.g., sys_nanosleep (27814) returns EINVAL if
the supplied value was out of range - It is the callers job to interpret the meaning
of EINVAL
7- Examples of System Calls
- 373 ENTRY(sys_call_table)
- 374 .long SYMBOL_NAME(sys_ni_syscall) / 0
/ - 375 .long SYMBOL_NAME(sys_exit)
- 376 .long SYMBOL_NAME(sys_fork)
- 377 .long SYMBOL_NAME(sys_read)
- 378 .long SYMBOL_NAME(sys_write)
- 379 .long SYMBOL_NAME(sys_open) / 5
/ - 380 .long SYMBOL_NAME(sys_close)
- .long SYMBOL_NAME(sys_waitpid)
-
- 392 .long SYMBOL_NAME(sys_stat)
- 393 .long SYMBOL_NAME(sys_lseek)
- 394 .long SYMBOL_NAME(sys_getpid) / 20
/
8-
- 562 .long SYMBOL_NAME(sys_ni_syscall) /
streams1 / - 563 .long SYMBOL_NAME(sys_ni_syscall) /
streams2 / - .long SYMBOL_NAME(sys_vfork) / 190 /
-
- 572 .rept NR_syscalls-190
- 573 .long SYMBOL_NAME(sys_ni_syscall)
- .endr
- --- Repeat as many times as necessary to fill out
the table - --- NR_syscalls is set to 256
- --- System calls can be added or removed to the
table without changing the value of NR_syscalls
9- Example of Body of System Calls
- 27483 asmlinkage int sys_getpid(void)
- 27484
- 27485
- 27486 return current-gtpid
- 27487
- ----------
- 29185 asmlinkage int sys_ni_syscall(void)
- 29186
- 29187 return -ENOSYS
- 29188
- Here ni means not implemented
10- Sometimes, there is further function calls
- 27688 asmlinkage int sys_sched_setscheduler(pid_t
pid, - 27689 int policy, struct sched_param param)
- 27690
- 27691 return setscheduler(pid, policy, param)
- 27692
- ----------
- 27694 asmlinkage int sys_sched_setparam(pid_t
pid, - 27695 struct sched_param param)
- 27696
- 27697 return setscheduler(pid, -1, param)
- 27698
1127618 static int setscheduler(pid_t pid, int
policy, 27619 struct sched_param
param) 27620 27621 struct sched_param
lp 27622 struct task_struct p 27623 int
retval 27624 27625 retval -EINVAL 27626
if (!param pid lt 0) 27627 goto
out_nounlock 27628 27629 retval
-EFAULT 27630 if (copy_from_user(lp,
param, 27631 sizeof(struct
sched_param))) 27632 goto out_nounlock 27633
27634 / We play safe to avoid deadlocks.
/ 27635 spin_lock(scheduler_lock) 27636
spin_lock_irq(runqueue_lock) 27637
read_lock(tasklist_lock) 27638 27639 p
find_process_by_pid(pid)
1227641 retval -ESRCH 27642 if (!p) 27643
goto out_unlock 27644 27645 if (policy lt
0) 27646 policy p-gtpolicy 27647 else
27648 retval -EINVAL 27649 if
(policy ! SCHED_FIFO policy ! SCHED_RR
27650 policy ! SCHED_OTHER) 27651
goto out_unlock 27652 27653
1327654 / Valid priorities for SCHED_FIFO and
SCHED_RR are 27655 1..99, valid priority for
SCHED_OTHER is 0. / 27656 retval
-EINVAL 27657 if (lp.sched_priority lt 0
lp.sched_priority gt 99) 27658 goto
out_unlock 27659 if((policy SCHED_OTHER) !
(lp.sched_priority 0)) 27660 goto
out_unlock 27661 27662 retval -EPERM 27663
if ((policy SCHED_FIFO policy
SCHED_RR) 27664 !capable(CAP_SYS_NICE)) 2
7665 goto out_unlock
1427666 if ((current-gteuid ! p-gteuid) 27667
(current-gteuid ! p-gtuid) 27668
!capable(CAP_SYS_NICE)) 27669 goto
out_unlock 27670 27671 retval 0 27672
p-gtpolicy policy 27673 p-gtrt_priority
lp.sched_priority 27674 if (p-gtnext_run) 27675
move_first_runqueue(p) 27676 27677
current-gtneed_resched 1 27678 27679
out_unlock 27680 read_unlock(tasklist_lock) 2
7681 spin_unlock_irq(runqueue_lock) 27682
spin_unlock(scheduler_lock) 27683 27684
out_nounlock 27685 return retval 27686
15- How System Calls Are Invoked
- A system call represents a transition from user
mode to system mode, using (software) interrupt
0x80 - 1713 define SYSCALL_VECTOR 0x80
- 6828 set_system_gate(SYSCALL_VECTOR,system_call)
- The user calls a lib function, e.g., fork()
- Then the lib function trigs the 0x80 (software)
interrupt - This starts at ENTRY(system_call)(line 171-249),
in the entry.S file
16- / linux/arch/i386/entry.S
- entry.S contains the system-call and fault
low-level handling routines. This also contains
the timer-interrupt handler / - The code staring at system_call is an interrupt
handler - Fig. 5.1 (p. 452) shows a flow control graph
- We may explain it with the C style
17- The normal entry point is label system_call
- The normal exit point is label restore_all
- 172 pushl eax
- --- The EAX register contains the system calls
ID and up to 6 arguments. They are copied to the
stack - 173 SAVE_ALL
- --- Defined in line 85
- --- All registers are copied into the stack
1885 define SAVE_ALL
\ 86 cld
\ 87 pushl es
\ 88 pushl ds
\ 89 pushl eax
\ 90 pushl ebp
\ 91 pushl edi
\ 92 pushl esi
\ 93 pushl edx
\ 94 pushl ecx
\ 95 pushl ebx
\ 96 movl (__KERNEL_DS),edx
\ 97 movl dx,ds
\ 98 movl dx,es
19174 GET_CURRENT(ebx) --- Put the current
pointer into ebx 131 define GET_CURRENT(reg)
\ 132 movl esp, reg
\ 133 andl -8192, reg --- Each
process is allocated 8KB for its PCB and kernel
mode process stack --- Right after switching
from user mode to kernel mode, the esp register
points to the stack top, which is the end of the
8KB portion --- The PCB starts from the
beginning of the 8KB portion