西電-Linux上機(jī)-Modern-Operating-Systems-現(xiàn)代操作系統(tǒng)-課件_第1頁
西電-Linux上機(jī)-Modern-Operating-Systems-現(xiàn)代操作系統(tǒng)-課件_第2頁
西電-Linux上機(jī)-Modern-Operating-Systems-現(xiàn)代操作系統(tǒng)-課件_第3頁
西電-Linux上機(jī)-Modern-Operating-Systems-現(xiàn)代操作系統(tǒng)-課件_第4頁
西電-Linux上機(jī)-Modern-Operating-Systems-現(xiàn)代操作系統(tǒng)-課件_第5頁
已閱讀5頁,還剩53頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

操作系統(tǒng)課程設(shè)計(jì)標(biāo)題添加點(diǎn)擊此處輸入相關(guān)文本內(nèi)容點(diǎn)擊此處輸入相關(guān)文本內(nèi)容總體概述點(diǎn)擊此處輸入相關(guān)文本內(nèi)容標(biāo)題添加點(diǎn)擊此處輸入相關(guān)文本內(nèi)容實(shí)驗(yàn)內(nèi)容2系統(tǒng)調(diào)用題目要求為L(zhǎng)inux內(nèi)核增加一個(gè)系統(tǒng)調(diào)用,并編寫用戶進(jìn)程的程序來測(cè)試。要求該系統(tǒng)調(diào)用能夠完成以下功能:1.該系統(tǒng)調(diào)用有1個(gè)int型參數(shù),返回值為int。2.若參數(shù)大于0,則返回自己學(xué)號(hào)的最后一位。如學(xué)號(hào)為13091248

,則返回8。3.若參數(shù)小于或等于0,則返回自己的學(xué)號(hào)后三位。如學(xué)號(hào)為13091248,則返回248。系統(tǒng)調(diào)用系統(tǒng)調(diào)用內(nèi)核為用戶進(jìn)程提供的服務(wù);提供用戶模式的進(jìn)程和硬件設(shè)備的接口;保護(hù)對(duì)內(nèi)核所管理的資源的訪問,提高系統(tǒng)安全;提高程序的可移植性;Linux系統(tǒng)調(diào)用在內(nèi)核中全部以“sys_”開頭,如sys_fork,sys_exit.系統(tǒng)調(diào)用SYSCALL、libc、APIsys_fork()sys_write()

sys_...

…Kernelfork()libcAppcall

fork()/printf()/strlen()/…printf()

write()

strlen()

…用戶空間內(nèi)核空間Hardware系統(tǒng)調(diào)用實(shí)現(xiàn)include/asm/unistd.h中定義了所有系統(tǒng)調(diào)用的編號(hào)跳轉(zhuǎn)表以系統(tǒng)調(diào)用編號(hào)為下標(biāo),大小由NR_syscalls確定[include/linux/sys.h]沒有定義的跳轉(zhuǎn)表項(xiàng),一律指向函數(shù)sys_ni_syscall()/*kernel/sys.c*/{return

-ENOSYS;}增加系統(tǒng)調(diào)用1.

修改usr/src/linux/arch/i386/kernel/entry.S(S必須為大寫),找Entry(sys_call_table)增加新的系統(tǒng)調(diào)用表項(xiàng):修改前的代碼:.long

SYMBOL_NAME(sys_ni_syscall).long

SYMBOL_NAME(sys_vfork)/*

streams2*//*

190

*//**

NOTE!!

...*/.rept

NR_syscalls

-190.long

SYMBOL_NAME(sys_ni_syscall)需要修改系統(tǒng)調(diào)用實(shí)現(xiàn)1.

修改usr/src/linux/arch/i386/kernel/entry.S,增加新的系統(tǒng)調(diào)用表項(xiàng):修改后的代碼:.long

SYMBOL_NAME(sys_ni_syscall)/*

streams2

*/190.longSYMBOL_NAME(sys_vfork)/*

190*/.longSYMBOL_NAME(sys_mycall)/*191*//**

NOTE!!

...*/.rept

NR_syscalls

-

191.long

SYMBOL_NAME(sys_ni_syscall)課設(shè)題目的系統(tǒng)調(diào)用函數(shù)題目要求的系統(tǒng)調(diào)用函數(shù)可能形如asmlinkage

int

sys_mycall(int

num)

{if(num

>

0){

return

2;}else

{

return

13081032;}}系統(tǒng)調(diào)用實(shí)現(xiàn)3.

修改usr/include/asm/unistd.h,增加新的系統(tǒng)調(diào)用編號(hào):#define

NR_mycall

191 /*

my

syscall

*/4.

通過編譯產(chǎn)生新內(nèi)核,并重啟操作系統(tǒng)。Linux內(nèi)核的構(gòu)建確保是root用戶cd

/usr/src/linux依次執(zhí)行以下make語句make

mrpropermakeclean文件*//*

清理舊的配置信息*//*清理上次構(gòu)建時(shí)生成的make

menuconfig/*

進(jìn)入后直接Exit并且save*/make

dep

檢查各模塊的依賴關(guān)系make

bzImage

生成新內(nèi)核(壓縮格式),Linux內(nèi)核的構(gòu)建將新內(nèi)核復(fù)制到/boot下:cparch/i386/boot/bzImage

/boot/bzImage-new注意:此處arch為相對(duì)路徑,完整路徑前面有/usr/src/linux修改LILO配置文件/etc/lilo.conf,在尾部添加(不能 修改原有內(nèi)容)運(yùn)行:/sbin/lilo6.重啟虛擬機(jī):reboot,系統(tǒng)啟動(dòng)時(shí)按tab選擇新的內(nèi)核image=

/boot/bzImage-newlabel=linux-newroot=/dev/sda5initrd=/boot/initrd.imgappend=“”read-only應(yīng)與其他引導(dǎo)內(nèi)核相同這里與其他內(nèi)核相同應(yīng)與其他引導(dǎo)內(nèi)核相同應(yīng)與其他引導(dǎo)內(nèi)核相同系統(tǒng)調(diào)用實(shí)現(xiàn)如何使用系統(tǒng)調(diào)用

對(duì)于內(nèi)核本身提供的系統(tǒng)調(diào)用,在libc中都已經(jīng)提供了相應(yīng)的API,可以當(dāng)做普通的庫函數(shù)調(diào)用:對(duì)于自定義的系統(tǒng)調(diào)用,需要經(jīng)過特殊處理:#include

<linux/unistd.h>/*

generate

the

stub

for

our

new

syscall*

int sys_mycall(int

a,

int

b)*/_syscall2

(int,

mycall,int,

a, int,

b);//注意參數(shù)與mycall要求的參數(shù)一致課設(shè)題目的測(cè)試函數(shù)題目要求的測(cè)試函數(shù)可能形如#include

<linux/unistd.h>_syscall1(int,mycall,int,ret);//假設(shè)mycall接受一個(gè)int參數(shù)int

main(){printf("My

name

is

XXX,and

my

number

is%d.\n",mycall(0));printf("The

last

of

my

numberis%d.\n",mycall(1));return

0;}說明使用2.4或更高版本的內(nèi)核可獲得加分參考資料:google搜索“l(fā)inux增加系統(tǒng)調(diào)用”實(shí)驗(yàn)內(nèi)容3

Device

DriverLinux設(shè)備分類字符設(shè)備

(character

devices)以字符為單位進(jìn)行I/O操作;只能順序存?。粺o需緩沖區(qū);如:Keyboard,Serial

Port塊設(shè)備

(blockdevices

)以固定大小的數(shù)據(jù)塊為單位進(jìn)行I/O操作;數(shù)據(jù)塊可以被隨機(jī)存?。恍枰欢▋?nèi)存做為緩沖區(qū);如:HD,CDROM,Floppy網(wǎng)絡(luò)設(shè)備

(Network

devices)面向數(shù)據(jù)包的傳輸設(shè)備在文件系統(tǒng)中沒有相應(yīng)的inode表示,只有一個(gè)符號(hào)名,如eth0。Linux將硬件設(shè)備看做一類特殊的文件(/dev/*)Linux的設(shè)備管理是和文件系統(tǒng)緊密結(jié)合的,各種設(shè)備都以文件的形式存放在/dev目錄下,稱為設(shè)備文件。應(yīng)用程序可以打開、關(guān)閉和讀寫這些設(shè)備文件,完成對(duì)設(shè)備的操作,就像操作普通的數(shù)據(jù)文件一樣設(shè)備是應(yīng)用訪問設(shè)備的途徑;設(shè)備文件代表一個(gè)驅(qū)動(dòng)程序的入口及與之相關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu);為設(shè)備編寫幾個(gè)基本的函數(shù),向虛擬文件系統(tǒng)(VFS)注冊(cè)就可以完成設(shè)備驅(qū)動(dòng)程序;安裝設(shè)備驅(qū)動(dòng)程序就是將該設(shè)備的操作函數(shù)集在內(nèi)核中注冊(cè)。/proc/devices列出系統(tǒng)當(dāng)前的設(shè)備。設(shè)備文件設(shè)備文件的3個(gè)基本屬性:類型:Block

orcharacter主設(shè)備號(hào)(Major

number)說明設(shè)備的類型(1

to

255)和各個(gè)設(shè)備驅(qū)動(dòng)相關(guān)

次設(shè)備號(hào)(Minor

number)

區(qū)分使用同一驅(qū)動(dòng)程序的不同設(shè)備。創(chuàng)建設(shè)備文件:

mknod

/dev/foo

b

60

0主設(shè)備號(hào)60,次設(shè)備號(hào)0

例:運(yùn)行命令

’ls

-l /dev/hda*

/dev/tty[012]’查看設(shè)備的3個(gè)屬性設(shè)備文件brw-rw----1rootcdrom3,0May61998hdabrw-rw----1rootdisk3,1May61998hda1brw-rw----1rootdisk3,2May61998hda2brw-rw----1rootdisk3,3May61998hda3crw-------1rootroot4,0

Dec

29

09:55

tty0crw-------1rootroot4,1Dec2909:56tty1crw-------1rootroot4,2Dec2909:56tty2Documentation/devices.txt設(shè)備驅(qū)動(dòng)程序用戶進(jìn)程請(qǐng)求設(shè)備服務(wù)流程圖用戶進(jìn)程V

F

S設(shè)備驅(qū)動(dòng)程序設(shè)備控制器設(shè)備本身OS可管轄范圍設(shè)備制造商范圍1.

用戶進(jìn)程發(fā)出I/O請(qǐng)求,系統(tǒng)將請(qǐng)求處理下傳到VFS上;VFS通過驅(qū)動(dòng)程序提供的接口將任務(wù)分配到驅(qū)動(dòng)程序;驅(qū)動(dòng)程序根據(jù)需要對(duì)設(shè)備控制器進(jìn)行操作;4.

設(shè)備控制器去控制設(shè)備。VFSLinux文件管理模塊包括2

部分實(shí)現(xiàn):文件系統(tǒng)無關(guān)部分定義文件管理的通用工作,如檢查訪問權(quán)限、確定磁盤塊需要讀寫的時(shí)機(jī)等。文件系統(tǒng)相關(guān)部分定義與具體文件系統(tǒng)相關(guān)的工作,如確定磁盤塊的定位、指引設(shè)備驅(qū)動(dòng)讀寫特定的塊等。內(nèi)核通過一個(gè)抽象層隱藏了特定文件系統(tǒng)的實(shí)現(xiàn)

細(xì)節(jié),并通過該抽象層管理多個(gè)不同的文件系統(tǒng);該抽象層就是Virtual

File

System

(VFS)。物理文件系統(tǒng)層VFSMINIXEXT2MSDOS用戶進(jìn)程內(nèi)核其他子系統(tǒng)內(nèi)

間用戶空間VFS設(shè)備驅(qū)動(dòng)程序設(shè)備緩存VFS對(duì)下:管理各物理文件系統(tǒng)設(shè)備驅(qū)動(dòng)程序組成設(shè)備服務(wù)子程序每個(gè)服務(wù)子程序只處理一種設(shè)備或與其緊密相關(guān)的設(shè)備;從與設(shè)備無關(guān)的軟件中接受抽象的命令并執(zhí)行;中斷處理子程序主要用來檢測(cè)I/O操作是否完成,以喚醒被阻塞的進(jìn)程。特點(diǎn)驅(qū)動(dòng)程序?qū)儆趦?nèi)核代碼的一部分,運(yùn)行在內(nèi)核空間;向OS內(nèi)核提供統(tǒng)一接口,便于內(nèi)核對(duì)設(shè)備的管理;在編譯內(nèi)核時(shí),連入內(nèi)核的設(shè)備驅(qū)動(dòng)程序是可以配置的;多以內(nèi)核模塊方式實(shí)現(xiàn),使系統(tǒng)資源有效利用。設(shè)備驅(qū)動(dòng)程序管理I/O操作結(jié)束的策略:內(nèi)核發(fā)出I/O請(qǐng)求后等待(不可行的方式)輪詢內(nèi)核發(fā)出I/O請(qǐng)求后,驅(qū)動(dòng)程序啟動(dòng)設(shè)備;內(nèi)核周期性地查詢?cè)O(shè)備狀態(tài),直到設(shè)備完成I/O操作;中斷驅(qū)動(dòng)程序啟動(dòng)設(shè)備,同時(shí)自行掛起(suspend),直到設(shè)備完成并引發(fā)一個(gè)中斷請(qǐng)求(IRQ);IRQ一發(fā)生,相應(yīng)的中斷服務(wù)程序(ISR)將被運(yùn)行;用戶進(jìn)程被喚醒(waked

up)。struct

f…

…ile

{…dentry

*f_dentry;//設(shè)備文件的inode,dentry為目nux文件系統(tǒng)中某個(gè)索引節(jié)點(diǎn)(inode)的鏈接。file_operation

*f_op; //設(shè)備文件的操作集合struct錄項(xiàng),是Listruct…

…}設(shè)備驅(qū)動(dòng)程序-設(shè)備文件structfile_operations{…ssize_t(*read)(struct

file*,char

*,size_t,loff_t*);ssize_t(*write)(struct

file

*,

const

char

*,

size_t,loff_t*);int

(*open)(struct

inode

*,

struct

file

*);int

(*release)(struct

inode

*,

struct

file

*);unsigned

int

(*poll)

(struct

file

*,

structpoll_table_struct

*);…}設(shè)備驅(qū)動(dòng)的注冊(cè)和管理內(nèi)核設(shè)備驅(qū)動(dòng)程序表結(jié)構(gòu)(fs/devices.c) struct device_struct

{const

char

*name; //

devicenamestruct

file_operations

*

fops;};字符設(shè)備驅(qū)動(dòng)程序:設(shè)備表:全局?jǐn)?shù)組chrdevs[255],主設(shè)備號(hào)是它的下標(biāo)向系統(tǒng)注冊(cè)設(shè)備驅(qū)動(dòng):register_chrdev()/unregister_chrdev()缺省操作集合:file_ops:

def_chr_fops,僅定義了一個(gè)open方法;inode_ops:chrdev_inode_operations,僅定義了其中的file_operation=&def_chr_fops.Kernel

Module一段被獨(dú)立編譯的函數(shù)和數(shù)據(jù)的集合;可以被動(dòng)態(tài)加載/卸載,加載成功后,其中代碼、數(shù)據(jù)稱為內(nèi)核中的一部分;模塊技術(shù)通常用于實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)程序、文件系統(tǒng)、網(wǎng)絡(luò)協(xié)議、系統(tǒng)調(diào)用等;模塊優(yōu)點(diǎn):可根據(jù)需要,在不重新編譯內(nèi)核的情況下,將新代碼插入到內(nèi)核而成為內(nèi)核的有機(jī)組成;使得內(nèi)核在內(nèi)存的映像較??;具有更大的靈活性和可擴(kuò)充性;調(diào)試方便。Kernel

Module命令lsmod(和文件/proc/modules)可列出了當(dāng)前已經(jīng)加載的所有模塊,每個(gè)入口對(duì)應(yīng)一個(gè)模塊:模塊名占用內(nèi)存大小使用模塊列表iptable_nat22904ip_conntrack29696[iptable_nat]iptable_mangle2776ide-cd35772cdrom34176[ide-cd]mousedev5656input6208[keybdev

mousedevhid]structmodule{

//

內(nèi)存中的每個(gè)module,位于include/linux/module.hunsigned

long

size_of_struct;

//

==sizeof(module)struct

module

*next;

//將所有module構(gòu)成一個(gè)鏈表const

char

*name;unsigned

long

size;//module名//以頁為單位的模塊大小union{atomic_t

usecount;long

pad;}uc;

//使用記數(shù)usagecounterunsigned

long

flags;unsigned

nsyms;struct

module_symbol

*syms;//AUTOCLEAN

et

al//該模塊的符號(hào)表中元素個(gè)數(shù)//該模塊export的符號(hào)表//本模塊指向其他模塊的個(gè)數(shù),定義模塊時(shí)已知//被依賴模塊的數(shù)組(鏈)//引用本模塊的模塊列表(鏈),動(dòng)態(tài)可unsigned

ndeps;struct

module_ref*deps;struct

module_ref

*refs;變,便于查詢//模塊初始化函數(shù)指針//模塊清理函數(shù)指針……

……int

(*init)(void);void

(*cleanup)(void);};模塊初始原型:int主要完成模塊清理原型:voi完成卸載塊API其它函數(shù)化函數(shù)(必須定義)init_module(void);模塊初始化、登記模塊API函數(shù)(必須定義)d

clean_module(void);模塊時(shí)的清理工作、取消登記的模,數(shù)據(jù)結(jié)構(gòu)、變量等符號(hào)。模塊中的內(nèi)//容模塊中的代碼運(yùn)行于核心態(tài)#include

<linux/kernel.h>#include

<linux/module.h>int init_module(

){printk("Hello,

world\n");return

0;}void

cleanup_module(

){printk("Goodbye

myworld\n");}在Linux里,除了直接修改系統(tǒng)核心的源代碼,把設(shè)備驅(qū)動(dòng)程序加進(jìn)核心里以外,還可以把設(shè)備驅(qū)動(dòng)程序作為可加載的模塊,由系統(tǒng)管理員動(dòng)態(tài)地加載和卸載。Linux的模塊可以用C語言編寫,用gcc編譯成目標(biāo)文件(不進(jìn)行鏈接,作為*.o文件存在),為此需要在gcc命令行里加上-c的參數(shù)。在編譯時(shí),還應(yīng)該在gcc的命令行里加上這樣的參數(shù):-D_KERNEL_-DMODULE。由于在不鏈接時(shí),gcc只允許一個(gè)輸入文件,因此一個(gè)模塊的所有部分都必須在一個(gè)文件里實(shí)現(xiàn)。內(nèi)核模塊的管理內(nèi)核模塊的管理編譯好的模塊*.o放在/lib/modules/xxxx/misc下(xxxx表示核心版本,如在核心版本為2.2.14時(shí)應(yīng)該為/lib/modules/2.2.14/misc)然后用depmod-a使此模塊成為可加載模塊。模塊用

insmod命令可手工裝入內(nèi)核模塊,用rmmod命令可以卸載指定的模塊,并可以用lsmod命令可查看當(dāng)前裝入的內(nèi)核模塊狀態(tài)以及需求加載模塊的使用計(jì)數(shù)及標(biāo)志信息。在成功的向系統(tǒng)注冊(cè)了設(shè)備驅(qū)動(dòng)程序后(調(diào)用

register_chrdev成功后),就可以用mknod命令來把設(shè)備映射為一個(gè)特別文件,其它程序使用這個(gè)設(shè)備的時(shí)候,只要對(duì)此特別文件進(jìn)行操作就行了。37Module管理接口System

Call

for

module

loadingallocate

space

for

a

moduleInitialize

a

moduleQuery

information

of

a

modulecreate_module(),init_module(),query_module(),delete_module(),get_kernel_syms()System

utilities:/sbin/insmod (安裝模塊)/sbin/rmmod (卸載模塊)/sbin/lsmod (顯示已加載模塊)/sbin內(nèi)的命令必須要root權(quán)限,主要是用于系統(tǒng)管理(而非普通使用)的命令小例子[root#]insmod

./hello.o(此處可能出現(xiàn)linux內(nèi)核版本不一致,可在啟動(dòng)時(shí)選用做系統(tǒng)調(diào)用實(shí)驗(yàn)時(shí)編譯的內(nèi)核)Hello,world[root#]

rmmod

helloGoodbye

my

world#include

<linux/kernel.h>#include

<linux/module.h>模塊初始化函數(shù)int init_module()

{

printk("Hello,

world\n");

return

0;}void

cleanup_module()

{

printk("Goodbye

my

world\n");}模塊清理函數(shù)編譯、安裝、卸載:[root#]

gcc

–c

–Wall

–D

KERNEL

-DMODULE

hello.c信息也被記錄在/var/log/messages字符設(shè)備實(shí)驗(yàn)內(nèi)容實(shí)現(xiàn)一個(gè)字符設(shè)備,支持以下功能:用戶可以向設(shè)備寫入字符串,并覆蓋設(shè)備中原有的字符串;用戶可以從設(shè)備讀出寫入的字符串;用戶通過系統(tǒng)調(diào)用ioctl清除設(shè)備中寫入的字符串;設(shè)備關(guān)閉前,只能被打開一次.O_RDONLY);sizeof(yourmsg));件結(jié)束close(h);,

O_WRONLY);表示寫入的字節(jié)der //

process

2:

writer000]; char

yourmsg[1000];BUF_DEV, int

h

=

open(RWBUF_DEV//打開設(shè)備失敗時(shí)h<0h

<

0

int

n

=write

(h,yourmsg,ourmsg,

sizeof(yourmsg)+1);//寫設(shè)備失敗時(shí)n<0,否則<0,n=0表示文數(shù)close(h);//

process

1: rea

//

process

3:

cleanerchar

yourmsg[1 char

yourmsg[1000];int

h

=

open(RW

int

h

=

open(RWBUF_DEV,

O_RDWR);//打開設(shè)備失敗時(shí)h<0//打開設(shè)備失敗時(shí)int

n=ioctl

(h,

RW_CLEAR,0);int

n=read

(h,

y

//寫設(shè)備失敗時(shí)n<0,否則表示成功//讀設(shè)備失敗時(shí)n

close(h);字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//

rwbuf.h, driver

for

virtual

char-device#define

RWBUF_NAME

“rwbuf”//設(shè)備文件/dev/rwbuf#defineRWBUF_DEV“/dev/rwbuf”//

devicepath#defineRWBUF_MAJOR60//主設(shè)備號(hào)#defineRWBUF_CLEAR0x909090//

IO

CtrlCommand//

rwbuf.c, driver

for

virtual

char-device#include

“rwbuf.h”#include

<linux/kernel.h>#include

<linux/module.h>#include

<linux/fs.h>//

for

kernelprogramming// for

kernel

module

struct.// struct

file_operations可以不單獨(dú)寫.h文件//rwbuf.c, driver

for

virtual

char-deviceint

init_module(){printk("Hello

world\n");if

(

register_chrdev(RWBUF_MAJOR,RWBUF_NAME,&rwbuf_fops)){printk("register

error\n");return

-1;}printk("register

ok\n");return

0;}字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//rwbuf.c, driver

for

virtual

char-devicestatic

struct

file_operationsrwbuf_fops

={open:

rwbuf_open,release:

rwbuf_close,read:write:ioctl:rwbuf_read,rwbuf_write,rwbuf_ioctl,};//rwbuf.c, driver

for

virtual

char-devicevoid

cleanup_module(){if(unregister_chrdev(RWBUF_MAJOR,RWBUF_NAME)

!=0

)printk("unreg

err\n");elseprintk("unreg

ok\n");printk("bye\n");}字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//rwbuf.c, driver

for

virtual

char-devicestatic

struct

file_operationsrwbuf_fops

={open:

rwbuf_open,release:

rwbuf_close,read:write:ioctl:rwbuf_read,rwbuf_write,rwbuf_ioctl,};字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//

rwbuf.c,

driver

for

virtual

char-devicestatic

int

inuse=0;//only

one

process

permited

at

the

same

time,類似于一個(gè)鎖

static

int

rwbuf_open(struct

inode

*inode,struct

file

*

filep){if

(inuse

==

1)

return

-1;inuse

=

1;MOD_INC_USE_COUNT; //

increase

the

use

count

in

struct

modulereturn

0;}static

int

rwbuf_close(

struct

inode

*inode,

struct

file

*

filep

)

{inuse

=

0;MOD_DEC_USE_COUNT;return

0;}字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//

rwbuf.c,

driver

for

virtual

char-device#define

rwbuf_size

200static

char

rwbuf[rwbuf_size];//

MAX

size

of

buffer//

the

buffer

keeping

stringstaticint rwlen

=

0;

//

length

ofstringstatic

ssize_t

rwbuf_write

(

struct

file

*

filep,const

char

*buf,{size_t

count, loff_t

*

ppos

)//判斷寫入的長(zhǎng)度是否有效copy_from_user(rwbuf,buf,count);//從用戶空間復(fù)制到內(nèi)核空間rwlen

=

count;//

print

some

message

byprintk();return

count;}字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//rwbuf.c, driver

for

virtual

char-devicestatic

ssize_t

rwbuf_read(

struct

file*

filep, char

*

buf,size_t

count, loff_t*

ppos){//判斷讀取的長(zhǎng)度是否有效copy_to_user(buf,rwbuf,count);//從內(nèi)核空間復(fù)制到用戶空間//

print

some

message

byprintk()return

count;}字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)//

rwbuf.c,

driver

for

virtual

char-devicestatic

int

rwbuf_ioctl

(

struct

inode*inode, struct

file

*filep,unsigned

int

cmd,unsigned

long

arg

){if

(

cmd

==

RW_CLEAR

)

{rwlen

=

0; //

clear

buf

by

set

its

len

to

zeroprintk("rwbuf

in

kernel

zero-ed\n");break;};return

0;}字符設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)編譯gcc

–crwbuf.c

–D

KERNEL

-DMODULE

–Wall安裝與卸載:mknod

/dev/rwbuf

c600創(chuàng)建設(shè)備文件/sbin/insmod

rwbuf.o安裝設(shè)備驅(qū)動(dòng)/sbin/rmmod

rwbuf卸載設(shè)備驅(qū)動(dòng)加分點(diǎn)使用2.4或2.6內(nèi)核實(shí)驗(yàn)內(nèi)容4SpinLock目標(biāo):從實(shí)踐中理解OS內(nèi)核的加鎖機(jī)制和進(jìn)程調(diào)度算法的設(shè)計(jì),初步了解C語言和匯編語言的混合編程實(shí)驗(yàn)要求:使用spinLock、共享內(nèi)存調(diào)用實(shí)現(xiàn)三個(gè)應(yīng)用進(jìn)程按指定順序進(jìn)行執(zhí)行。(監(jiān)控進(jìn)程控制

3個(gè)進(jìn)程的可執(zhí)行位,依次放開3個(gè)進(jìn)程)參考資料:/wiki/自旋鎖什么是自旋鎖?自旋鎖是專為防止多處理器并發(fā)而引入的一種鎖,它在內(nèi)核中大量應(yīng)用于中斷處理等部分。自旋鎖最多只能被一個(gè)內(nèi)核任務(wù)持有如果一個(gè)內(nèi)核任務(wù)試圖請(qǐng)求一個(gè)已被持有的自旋鎖,那么這個(gè)任務(wù)就會(huì)一直進(jìn)行忙循環(huán)——旋轉(zhuǎn)——等待鎖重新可用。即每個(gè)進(jìn)程不斷試圖獲得鎖,直到獲得鎖為止。要是鎖未被持有,請(qǐng)求它的內(nèi)核任務(wù)便能立刻得到它并且繼續(xù)進(jìn)行。自旋鎖不允許任務(wù)睡眠(持有自旋鎖的任務(wù)睡眠會(huì)造成自死鎖,因?yàn)樗哂锌赡茉斐沙钟墟i的內(nèi)核任務(wù)被重新調(diào)度,而再次申請(qǐng)自己已持有的鎖),它能夠在中斷上下文中使用。什么是自旋鎖?自旋鎖的初衷:在短期間內(nèi)進(jìn)行輕量級(jí)的鎖定。一個(gè)被持有的自旋鎖使得請(qǐng)求它的線程在等待鎖重新可用的期間進(jìn)行自旋(浪費(fèi)處理器時(shí)間),所以自旋鎖不應(yīng)該被持有時(shí)間過長(zhǎng)。正是由于自旋鎖使用者一般保持鎖時(shí)間非常短,因此選擇自旋而不是睡眠是非常必要的,自旋鎖的效率遠(yuǎn)高于互斥鎖。如果需要長(zhǎng)時(shí)間鎖定的話,最好使用信號(hào)量。當(dāng)一個(gè)進(jìn)程試圖獲得信號(hào)量而沒有獲得時(shí),它會(huì)進(jìn)入睡眠狀態(tài)。單CPU時(shí),自旋鎖會(huì)讓處理器動(dòng)不了。因此,一般自旋鎖實(shí)現(xiàn)會(huì)有一個(gè)參數(shù)限定最多持續(xù)嘗試次數(shù)實(shí)驗(yàn)內(nèi)容4SpinLock實(shí)現(xiàn)說明:i.環(huán)境:系統(tǒng)中共有a、b、c

3個(gè)應(yīng)用進(jìn)程、一個(gè)監(jiān)控進(jìn)程M和一個(gè)初始化進(jìn)程Init,此外系統(tǒng)中還有一個(gè)共享內(nèi)存SHM。SHM中有l(wèi)a,lb,lc

3個(gè)表示運(yùn)行的鎖變量,分屬于A、B、C

3個(gè)應(yīng)用進(jìn)程,每個(gè)應(yīng)用進(jìn)程都通過spinlock試圖獲得鎖,當(dāng)獲得鎖后,它就開始正常運(yùn)行。SHM中還有有3個(gè)分屬于各個(gè)進(jìn)程用來表示進(jìn)程是否結(jié)束的互斥變量ta,tb,tc,以及3個(gè)分別用來控制訪問ta、tb、tc的鎖變量lta、ltb、ltc.實(shí)現(xiàn)算法說明:Init進(jìn)程初始化共享內(nèi)存,并設(shè)置la、lb、lc、ta、tb、tc、lta、ltb、ltc的初值。接著Init進(jìn)程退出運(yùn)行。進(jìn)程i分別通過spinlock不停地試圖獲得li,一旦獲得,進(jìn)程就開始正常運(yùn)行。在進(jìn)程i退出前,通過spinlock試圖獲得lti,獲得lti后,進(jìn)程i將ti置為表示進(jìn)程結(jié)束的值,然后退出。監(jiān)控進(jìn)程M按照指定的調(diào)度順序逐步釋放li。每釋放一個(gè)li,M都要通過spinlock獲得lti,然后通過訪問ti,判斷i進(jìn)程是否結(jié)束,如果結(jié)束,那么M按照調(diào)度順序釋放下一個(gè)進(jìn)程j對(duì)應(yīng)的鎖變量lj。SpinLock的編寫算法思路1.保存現(xiàn)場(chǎng)(需要保存eax等spinlock函數(shù)用到的寄存器)2.利用原子指令cmpxchg(比較交換指令)嘗試加鎖3.利用cmpxchg指令執(zhí)行完畢后的標(biāo)志位,判斷是否已加鎖成功,若加鎖不成功,那么則通過跳轉(zhuǎn)指令繼續(xù)第2步。4.恢復(fù)現(xiàn)場(chǎng)SpinLock的編寫原子

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論