Date post: | 30-May-2018 |
Category: |
Documents |
Upload: | nguyenvan-thanh |
View: | 216 times |
Download: | 0 times |
of 33
8/9/2019 Linux Device Driver Sum Up 2
1/34
:XJKZQ+ZSHYNTSX
+ZSHYNTSare for doing device i/o, to/from the i/o ports
#include
char inb(int port);
char inw(int port);
char outb(char val, int port);
char outw(char val, int port);
+ZSHYNTSfor allocating small amounts of memory (
8/9/2019 Linux Device Driver Sum Up 2
2/34
#include
unsigned char get_fs_byte(const char *addr);
unsigned short get_fs_word(const short *addr);
unsigned long get_fs_long(const int *addr);void put_fs_byte(char val, char *addr);
void put_fs_word(short val, short *addr);
void put_fs_long(long val, int *addr);
void memcpy_fromfs(void *to, void *from, unsigned long len);
void memcpy_tofs(void *to, void *from, unsigned long len);
to set, clear, save and restore the interrupt enable flag
#include
void sti();
void cli();
void save_flags(unsigned long flags);
void restore_flags(unsigned long flags);
)WN[JW'FXNHX
SJJIYT\WNYJFSNSYNFQN_FYNTSWTZYNSJ
In order that the device driver is correctly initialized when
the operating system is booted, the xxx_init() routine must be
executed.
To ensure this happens, add the following line to the end of the
chr_drv_init() function in the
/usr/src/linux/driver/char/mem.c file:
mem_start = xxx_init(mem_start);
and resave the file back to disk.
8/9/2019 Linux Device Driver Sum Up 2
3/34
xxx_init()XMTZQIKNWXYHFQQregister_chrdev()YTWJLNXYJW
NYXJQKFSIF[TNIIJ[NHJSZRGJWHTSYJSYNTS
7JYZWSX
NKSTTYMJWHMFWFHYJWIJ[NHJMFXWJLNXYJWJI\NYM
YMJXFRJRFOTWSZRGJW
STSNKYMJHFQQKFNQXUWJXZRFGQ^GJHFZXJFSTYMJW
HMFWFHYJWIJ[NHJMFXFQWJFI^FQQTHFYJIYMFYRFOTW
SZRGJW
SJJIYT\WNYJKZSHYNTSXYTKNQQNSYMJXYWZHYKNQJDTUJWFYNTSX
XYWZHYZWJ
8/9/2019 Linux Device Driver Sum Up 2
4/34
:XNSL.SYJWWZUYX SJJIYT\WNYJFSNSYJWWZUYXJW[NHJWTZYNSJ.87
PJJUNSRNSIYMFYNSYJWWZUYXFWJFX^SHMWTSTZXYMJ^HFS
THHZWFYFS^YNRJ
void foo_interrupt(unsigned int irq, struct pt_reg *reg);
NWVNXYMJSZRGJWTKYMJNWV\MNHMYWNLLJWJIYMNXWTZYNSJ WJLXNXFHTU^TKYMJ(5:WJLNXYJWX
5. Kernel modules
from a source file mod.c of a kernel module, you compile it with gcc -Wall -O2
-c mod.c
Once you get the compiled mod.o, you can become root and install it to a
running kernel using insmod mod.o, and remove it from the kernel using
rmmod mod.
Most modules does not do a lot of things when being loaded. They just register
some functions to the kernel, so that when the functionalities are needed, those
8/9/2019 Linux Device Driver Sum Up 2
5/34
functions are called
/* define functions of the module */
int init_module(void) {
register_something(...);
return 0; /* should return 0 if succeed, non-zero if failure */
}
void cleanup_module(void) {
unregister_something(...);
}
/* extra information of the module */
Before you unload the module, you must unregister its major number. This can
be done by calling the function unregister_chrdev(unsigned int major, const
char *name). Again, negative values indicate error. The only possible error is
EINVAL
6. The in-kernel file structure
/**/ Represents open files in the kernel
similar to a FILE* in userspace. The current position in the file is stored here.
Created by the kernel on open call. Tuc la khi chung ta goi hamopen thi kernel se tao ra 1 file structure.
When a device is opened, a file structure is allocated and filled by the kernel to
keep information like
current access pointer
associated directory entry
open mode
file operations functions
The kernel will keep this structure until all references1 to it are removed, by
process being terminated, explicitly close() the file, or used dup2() whichimplicitly closed the file.
At that time the releasemethod is called, and the kernel deallocate the file
structure.
Thefile structure is defined in
loff_tf_pos: The current file position.
8/9/2019 Linux Device Driver Sum Up 2
6/34
struct file_operations *f_op; The operations associated with the file
void *private_data;
If the device driver writerwants to keep some data specific for the file
structure, it will allocate a structure (using kmalloc) and put the
pointer to the structure here when the device is first opened.
The open system call sets this pointer to null before calling the open
method for the driver.
private_data is a useful resource for preserving state information
across system call
7. The file operations
/**/ Connects system calls with our drivers code by providing pointers
to the drivers functions.
static intfoo_open(struct inode *inode, struct file *filp) Called when the file is opened.
The function should return 0 if it decides that the file opening is valid, and
return an error code (like EPERM) otherwise, explaining why the call
failed.
The device number can be found in the inodepassed to this function, using
8/9/2019 Linux Device Driver Sum Up 2
7/34
inode->i_rdev.
staticssize_tfoo_read(structfile *file, char * buffer,size_tcount, loff_t*filp);
This is called when the user program tries to read from the file.
At most count bytes should be written to the user-provided buffer,
probably using copy_to_useror one of its variants
The code should increment the number *filpby the number of bytes read.
The return value of this function should be the number of bytes read, or0
if it reaches the end of file, or a negative error code to indicate an error.
static ssize_tfoo_write(struct file *file, char * buffer, size_t count, loff_t
*filp);
This is called when the user program tries to write into the file.
At most count bytes should be copied from the user-provided buffer,
probably using copy_from_useror one of its variants.
The code should increment the number *filp by the number of bytes
written.
The return value of this function should be the number of bytes written, or
a negative error code to indicate error.
8. Inode
/**/ Represents files.
8/9/2019 Linux Device Driver Sum Up 2
8/34
Lots of fields but mostly 2 fields of interest for drivers if it is a
device file:
dev_t i_rdev;
/**/
struct cdev *i_cdev; cdev's an internal kernel stucture,
representing char devices
9. The File Systems VFS (Virtual File System)
All file systems in Linux rely on the VFS to allow them not only to
coexist, but also to interoperate.
This enables you to use standard Unix system calls to read and write
to different file systems on different media.
The purpose ofVFS is to maintain an interface between system calls
concerning files and the file management code proper
When a process performs a system call on files, it is directed at the
VFS The VFS is responsible for performing operations which are
independent of the format of the filesystem concerned
Then, the VFS redirects the request to the module managing the
file
8/9/2019 Linux Device Driver Sum Up 2
9/34
8/9/2019 Linux Device Driver Sum Up 2
10/34
inode
Every file and directory in the file system is described by one and onlyone
inode. The inodes for each block group are kept in the inode table together with
an inode (allocation) bitmap
Elements
mode: permissions
owner information: The user and group identifiers
8/9/2019 Linux Device Driver Sum Up 2
11/34
size
timestamps: The time that the inode was created
Datablocks
Pointers to the blocks that contains the data The first 12 are direct pointers to data blocks
The last three entries are for indirect blocks
File-System Control Blocks
8/9/2019 Linux Device Driver Sum Up 2
12/34
10.Tim d Tim M g m
Kernel notionofTime
Kernel n omprehend nd m nage time through ti
rate of y tem
timer inhard
are
When the y tem timer goes off, it issues an interrupt that the
ernel
handles viaaspecial interrupthandler
TheTick Rate: HZ Programmable Interval Timer
The tick rate is programmed on system boot based on a static
preprocessor define, HZ
The valueofHZ differsforeachsupported architectures
Thekernel definesthe value in
#define HZ 1000 /* internal kernel timefrequency */
When
riting kernel code, neverassumethatHZ hasany given value Jiffies
The global variable jiffiesholds thenumber of ticks thathave occurred
since thesystem booted
externunsigned long volatile jiffies; /* */
onboot: jiffies = 0;
eachtimer interrupt: jiffies++;
convertformsofjiffies
second to jiffies: ! second*HZ"
jiffiestosecond: #jiffies/HZ
$
ex
$
unsigned long next_tick = jiffies+_1;/* onetickfrom now */
unsigned long later = jiffies+ 5 * HZ; /* fivesecond from now */
% Internal RepresentationofJiffies
The jiffies variablehas 3&
bit insi' eon 3&
(bitarchitecturesand
)
0
(bit
on)
0
(bitarchitectures
overflow:1
2 .7days 3 1000HZ / 34
5bit)
6 macrosforcomparing tickcounts:
8/9/2019 Linux Device Driver Sum Up 2
13/34
#define time_after(unknown , known) ((long)(known)
(long)(unknown) < 0)
#define time_before(unknown, known) ((long)(unknown)
(long)(known) < 0)
#define time_after_eq(unknown, known) ((long)(unkown)
(long)(known)>= 0)
#define time_before_eq(unknown, known) ((long)(known)
(long)(unkown)>= 0)
7
Timers
8 Purpose: to delay executionofsomefunction until aspecified latertime
9 Timerusagesequence
specify anexpirationtime specify afunctiontoexecuteuponexpiration
activatethetimer
Timer is destroyed once itexpires
No limitonthenumberoftimers
@ represented bystructtimer_list
A Using:
8/9/2019 Linux Device Driver Sum Up 2
14/34
B Timer Related Functions:
Modify expirationofanactivetimer:
mod_timer(&my_timer, jiffies+new_delay)
Deactivateatimer: del_timer(&my_timer)
Delaying C xecution D mall Delays :
E Purpose:kernel code(especially drivers)needsaway to delay executionfor
sometimewithoutusing timersorbottomFhalfmechanism
usually toallowhardwaretimetocompletea giventask
networkcard drivershould waitat leastthetwo microsecondsbefore
continuing
G thesolutions(depending onthesemanticsofthe delay) Busy Looping
Small Delays
schedule_timeout()
H Busy looping: spin ina loop until the desired numberofclockticks pass
Busy Looping for10ticks: chu y rang jiffies isa volatile variable
unsigned long delay = jiffies+10;
while(time_before(jiffies, delay));
Busy looking forI
seconds:
unsigned long delay = jiffies+P
* HZ;
8/9/2019 Linux Device Driver Sum Up 2
15/34
while(time_before(jiffies, delay));
Q Small Delays:
ifyouneed precise delays, thesecallsare yourbestchoice
requires very shortand rather precise delays
kernel provide two functions for microsecond and millisecond
delays
delays execution by busy looping for the specified number of
microsecondsor milliseconds using thefunctions
theudelay()functionshould becalled only forsmall delays
larger delaysonfast machines mightresult inoverflow
as delaysover1 millisecondfor longer durationsmdelay()function
should becalled
R schedule_timeout(): nham muc dich dua1task vaotrang thai sleep trong 1
khoang thoi gian labao lau, sau dokernel sewake_up task do
optimal method:
tasktosleep until at leastthespecified timehaselapsed thekernel wakesthetaskup and places itbackontherunqueue
using thefunctions:
sleeping onawaiting queue, withatimeout
firstoccurwantto make desirabletowaitforaspecificeventor
waitforaspecified timetoelapse call schedule_timeout() instead ofschedule()after placing itselfon
awaitqueue
11.SystemSall in Linux
ioctl
int(*ioctl)(struct inode* inode, structfile*filp,unsigned intcmd, unsigned
8/9/2019 Linux Device Driver Sum Up 2
16/34
long arg);
inode filp fd
cmd
arg unsigned long
su dung thu vien sau: include/asm/ioctl.h
12.
schedule()
:T
include
asmlinkage void schedule(void); :
sleep_on()
:U
include
void sleep_on(struct wait_queueV V
p);void interruptible_sleep_on(struct wait_queue
V V
p);
:
Chuyen process vao trang thai sleed.
sleep_on()
wake_up() sleep_on() I/O I/O
Neu lenh sleep_on() duoc phat sinh thi process cua
driver se khogn the chuyen den buoc tiep theo, thuc hien cau lenh
tiep theo duoc. Chung ta se dung lenh wake_up() de thoat khoi
tinh trang sleep_on().Thuc chat cua lenh sleep_on() nay la phat ra
8/9/2019 Linux Device Driver Sum Up 2
17/34
cac cau lenh I/O vao hardware, va choW
` cho den khi cac I/O nay
thuc hien xong
DOS OS for()
Linux OS
sleep_on()
sleep_on() interruptible_sleep_on()
(^_^); interruptible_sleep_on()
SIGINT
wake_up()
:X
include
void wake_up(struct wait_queueY Y
q);
:
add_timer()
:
include
void add_timer(struct timer_lista
timer);
struct timer_list {
struct timer_lista
next; /a
NULL a
/
struct timer_lista
prev; /a
NULL a
/
unsigned long expires; /a
a
/
unsigned long data; /a
a
/
void (
a
function)(unsigned long); /
a
'data'
a
/
};
:
'expires' 'function'
del_timer()
8/9/2019 Linux Device Driver Sum Up 2
18/34
:b
include
int del_timer(struct timer_listc
timer);
:
'function'
udelay()
:d
include
__inline__ void udelay(unsigned long usecs);
:
verify_area() :
e
include
int verify_area(int type, const voidf
addr, unsigned long size);
:
ioctl() int
memcpy_fromfs()
:g
include
void memcpy_fromfs(voidi
to, voidi
from, int size);
:
De chuyen du lieu tu user space vao kernel space: The device
8/9/2019 Linux Device Driver Sum Up 2
19/34
driver copies data between the kernel'ys address space and
the user program'ys address space whenever the user makes
a read() or write() system call
Several Linux routines such as, memcpy_*fs() andput_fs*() enable device drivers to transfer data across
the usersystem boundary. Data may be transferred in bytes,
words, or in buffers of arbitrary sizes
For example, memcpy_fromfs() transfers an arbitrary
number of bytes of data from user space to the device,
while get_fs_byte() transfers a byte of data from user
space.
Similarly, memcpy_tofs() and put_fs_byte() write data to
user space memory memcpy_tofs()
:p
include
void memcpy_tofs(voidr
to, voidr
from, int size);
: memcpy_fromfs()
memcmp()
:s
include inline int memcmp(const void
t
cs,const voidt
ct,size_t count)
: memcmp( u )
kmalloc()
:v
include
voidw
kmalloc(int size, int priority);
: malloc( x )
request_irq()
:y
include y
include
8/9/2019 Linux Device Driver Sum Up 2
20/34
int request_irq(
unsigned int irq, /
/
void (
handler)(int, struct pt_regs
), /
/
unsigned long flags, /
(SA_INTE
UPT)
/const char
device); /
/
:
/proc/interrupt
free_irq()
:
include
void free_irq(unsigned int irq); /
arch/i86/kernel/irq.c
/
:
request_dma()
:
include int request_dma(
unsigned int dmanr, /
/
char
device_id); /
/
: /proc/dma
free_dma()
:
include
free_dma(unsigned int dmanr);
:
request_region()
:
include
int request_region(
unsigned int from, /
/unsigned int extent, /
/
const char
device_id); /
/
: /proc/ioports
8/9/2019 Linux Device Driver Sum Up 2
21/34
release_region()
:
include
int release_region(unsigned int from, /
/
unsigned int extent); /
/
:
check_region()
:
include
int check_region(
unsigned int from, /
/unsigned int extent); /
/
:
:
include
clear_dma_ff( );
set_dma_mode( , dma_mode); /
full address
/
set_dma_addr( , );set_dma_count( , );
enable_dma( );
:
static __inline__ void enable_dma(unsigned int dmanr)
static __inline__ void disable_dma(unsigned int dmanr)
static __inline__ void clear_dma_ff(unsigned int dmanr)
'DMAPointer Flip Flop'
clear_dma_ff(DMA);
outb();
8/9/2019 Linux Device Driver Sum Up 2
22/34
outb( );
clear_dma_ff(DMA);
= inb();
= inb();
static __inline__ void set_dma_mode(unsigned int dmanr, char
mode)
static __inline__ void set_dma_addr(unsigned int dmanr,
unsigned int a)
static __inline__ void set_dma_count(unsigned int dmanr,
unsigned int count)
static __inline__ int get_dma_residue(unsigned int dmanr)
register_chrdev()
:
include
int register_chrdev( /
linux/fs/devices.c
/
unsigned int ma
or, /
/
const char
name, /
/
struct file_operations
fops) /
/
struct file_operations { /
/
int (
lseek) (struct inode
, struct file
, off_t, int);int (
read) (struct inode
, struct file
, char
, int);
int (
write) (struct inode
, struct file
, char
, int);
int (
readdir) (struct inode
, struct file
, struct dirent
, int);
int (
select) (struct inode
, struct file
, int, select_table
);
int (
ioctl) (struct inode
, struct file
, unsigned int, unsigned
8/9/2019 Linux Device Driver Sum Up 2
23/34
long);
int (
mmap) (struct inode
, struct file
, struct vm_area_struct
);
int (
open) (struct inode
, struct file
);
void (
release) (struct inode
, struct file
);int (
fsync) (struct inode
, struct file
);
int (
fasync) (struct inode
, struct file
, int);
int (
check_media_change) (dev_t dev);
int (
revalidate) (dev_t dev);
};
:
file_operations
printk() printf()
:
include
asmlinkage int printk(const char
fmt, ...); /
printk.c
/
: printf( )
syslogd /var/log/syslog
send_sig()
:
include
int send_sig(unsigned long sig,struct task_struct
p,int priv) /
exit.c
/
:
notify_parent()
:
include void notify_parent(struct task_struct
j
tsk) /j
exit.cj
/
:
outb()
:k
include
8/9/2019 Linux Device Driver Sum Up 2
24/34
void outb(unsigned char value, unsigned address);
inb()
:l
include
void inb(unsigned address)
:
1m. file_operations : file_operations
register_chrdev()
(^_^);
open(): open(2) wd n n c_open()
static int wd n n c_open(
struct inodeo
inode, /o
inode o
/
struct file
o
filp, /
o
file o
/ /usr/include/linux/fs.h
struct inode {
kdev_t i_dev;
unsigned long i_ino;
8/9/2019 Linux Device Driver Sum Up 2
25/34
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
gid_t i_gid;kdev_t i_rdev;
off_t i_size;
time_t i_atime;
time_t i_mtime;
time_t i_ctime;
unsigned long i_blksize;
unsigned long i_blocks;
unsigned long i_version;
unsigned long i_nrpages;struct semaphore i_sem;
struct inode_operations
i_op;
struct super_block
i_sb;
struct wait_queue
i_wait;
struct file_lock
i_flock;
struct vm_area_struct
i_mmap;
struct page
i_pages;
struct dquot
i_dquot[MAXQUOTAS];
struct inode
i_next,
i_prev;struct inode
i_hash_next,
i_hash_prev;
struct inode
i_bound_to,
i_bound_by;
struct inode
i_mount;
unsigned short i_count;
unsigned short i_flags;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_sock;unsigned char i_seek;
unsigned char i_update;
unsigned short i_writecount;
union {
struct pipe_inode_info pipe_i;
8/9/2019 Linux Device Driver Sum Up 2
26/34
struct minix_inode_info minix_i;
struct ext_inode_info ext_i;
struct ext2_inode_info ext2_i;
struct hpfs_inode_info hpfs_i;struct msdos_inode_info msdos_i;
struct umsdos_inode_info umsdos_i;
struct iso_inode_info isofs_i;
struct nfs_inode_info nfs_i;
struct xiafs_inode_info xiafs_i;
struct sysv_inode_info sysv_i;
struct affs_inode_info affs_i;
struct ufs_inode_info ufs_i;
struct socket socket_i;void
generic_ip;
} u;
};
struct file {
mode_t f_mode; /
O_
EAD|O_WRITE
/
loff_t f_pos;
unsigned short f_flags; /
O_BINARY*/unsigned short f_count; /* */
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
struct file *f_next, *f_prev;
int f_owner; /* pid or -pgrp where SIGIO should be sent */
struct inode * f_inode;
struct file_operations* f_op;
unsigned long f_version;
void *private_data; /* needed for tty driver, and maybe others */
}; release(): open(2)
close(2) wd
c_release()
static void wd c_release(
struct inode * inode, /* inode */
8/9/2019 Linux Device Driver Sum Up 2
27/34
struct file * filp); /* file */
ioctl(): open(2) ioctl(2)
wd
c_ioctl()
static int wd c_ioctl(
struct inode * inode, /* inode */
struct file * filp, /* file */
unsigned int iocmd, /* */
unsigned long ioarg); /* */
14.
:
open
close
read
write
ioctl
15.Phan biet RTOS va LINUX
ITRON chang han thi truc tiep truy nhap xuong hardware, do vay khogn can
8/9/2019 Linux Device Driver Sum Up 2
28/34
dinhnghia driver, cung khong can co API.
Doi voi he dieu hanh Linux thi lai gom co 2 che do user mode va kernel mode.
Nhung ung dung application o user mode thi khogn the truy nhap truc tiep vao
hardware, application phai thong qua standard API(application interface),
khoi dong device driver, roi sau do moi co the truy nhap vao phan cung hardware
duoc.
8/9/2019 Linux Device Driver Sum Up 2
29/34
16.
Tu application su dung system call (la interface giua application va OS) denham muc dich truy xuat vao device. Chung ta co cac system call o application
nhu sau:
open
close
read
write
ioctl
chung ta khong the nhin thay device, ma chung ta chi co the nhin thay device
gia tuong thong qua 1 loai file dac biet/dev/xxx
khi ma tu application access vao device thi kernel se su dung number duoc
dinh nghia cho device, tim kiem bang device driver table thogn qua major number.
Major number dung de phan biet cac device khac loai voi nhau. Ngoai ra con
8/9/2019 Linux Device Driver Sum Up 2
30/34
1 tham so nua la minor number. Khi muon phan biet cac thiet bi co cung major
number hay noi cach khac la cung loai thiet bi thi ta dung minor number.Minor
number duoc ghi vao device special file(inode) tuy nhien khi kernel goi device
driver thi tham so minor number se duoc giao cho thiet bi. Ve phai device
thi minor number thuc chat la so thu tu cua port ma device duoc gan vao.
:
Device Driver Initialization
Chu y rang viec initialization
nay se duoc ghi vao device special file. Gom co 3 thong so: major number, device
name, function table
In order that the device driver is correctly initialized wh enthe operating system is booted, the xxx_init() routine must
be executed.
To ensure this happens, add the following line to the end
of the chr_drv_init() function in the
/usr/src/linux/driver/char/mem.c file:
8/9/2019 Linux Device Driver Sum Up 2
31/34
mem_start = xxx_init(mem_start);and resave the file back to disk.
Chu y cac ham sau:
Read:
copy_to_user
Write:
copy_from_user
Top alf:
Tuong ung voi cac system call o application chang han nhu system call
open(); read(); thi kernel se goi cac function tuong ung xxx_open();
xxx_read();
8/9/2019 Linux Device Driver Sum Up 2
32/34
Bottom
alf:
Thong qua interrupt o hardware se khoi dong^ cac handler()
Thuc chat o day chinh la sudung clock phan cunginterrupible_sleep_on()
Vi du:
read()
API
read() i/o
i/o
i/o
i/o
i/o
read()interrupible_sleep_on()
17.
i/o
Khi ma device ket thuc qua trinh xuly tin
hieu, nham muc dich thong bao cho kernel biet thi no phai su dungngat
Vi trong phan bottom half
thi chung ta co su dung cau lenhinterrupible_sleep_on()tuc la se dung
lai khogn hoat dong^, nham doi* cho viec ghi/ doc du lieu ra phancung ket
thuc. Khi viec ghi/doc nay ket thuc thi se xuat hien ngat, ngat nay se phai
lam nhiem vu wake_up_interruptible de cho ham bottom half xu ly tiep. Do vay
chung ta phai dang ky ngat int request_irq o application va o kernel thi chung
ta phai lam la xxx_interrupt(int irq)
API
8/9/2019 Linux Device Driver Sum Up 2
33/34
18.
Linux
Chung ta co 2 cach de co the dang ky device driver voi kernel
Cach thu nhat la bien device driver thanh static link voi kernel
Khi kernel compile
thi ket hop voi device driver de tro thanh 1 object
Khi kernel boot thi device driver se register
va initialization do vay co the su dung duoc ngay lap tuc
ITRON RTOS
Chu y rang phuong phap nay thi ta sedung static memory do vay
se lam ton^ bo^ nho* nhung lai dam bao duoc do^ an toan cao
8/9/2019 Linux Device Driver Sum Up 2
34/34
Linux
Most microkernel advantages due to modularity
Most modern operating systems implement kernel modules
Uses ob
ect-oriented approach.Tuc la se compile thanh 1 ob
ect Each talks to the others over known interfaces
19.