linux教程第08課內(nèi)存與設(shè)備管理_第1頁
linux教程第08課內(nèi)存與設(shè)備管理_第2頁
linux教程第08課內(nèi)存與設(shè)備管理_第3頁
linux教程第08課內(nèi)存與設(shè)備管理_第4頁
linux教程第08課內(nèi)存與設(shè)備管理_第5頁
已閱讀5頁,還剩38頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 程序的程序的鏈接鏈接和內(nèi)存和內(nèi)存裝入裝入 linux教程第08課內(nèi)存與設(shè)備管理 連續(xù)分配方式連續(xù)分配方式 單一連續(xù)分配單一連續(xù)分配 這是最簡單的一種存儲管理方式,但只能用于單用戶、 單任務(wù)的操作系統(tǒng)中。采用這種存儲管理方式時,可把內(nèi) 存分為系統(tǒng)區(qū)和用戶區(qū)兩部分,系統(tǒng)區(qū)僅提供給OS使用, 通常是放在內(nèi)存的低址部分;用戶區(qū)是指除系統(tǒng)區(qū)以外的 全部內(nèi)存空間, 提供給用戶使用。 linux教程第08課內(nèi)存與設(shè)備管理 固定分區(qū)分配固定分區(qū)分配 1. 劃分分區(qū)的方法劃分分區(qū)的方法 分區(qū)大小相等, 即使所有的內(nèi)存分區(qū)大小相等。 (2

2、) 分區(qū)大小不等。 linux教程第08課內(nèi)存與設(shè)備管理 2. 內(nèi)存分配內(nèi)存分配 固定分區(qū)使用表 linux教程第08課內(nèi)存與設(shè)備管理 4.2.3 動態(tài)分區(qū)分配動態(tài)分區(qū)分配 1. 分區(qū)分配中的數(shù)據(jù)結(jié)構(gòu)分區(qū)分配中的數(shù)據(jù)結(jié)構(gòu) 空閑分區(qū)表。 (2) 空閑分區(qū)鏈。 空閑鏈結(jié)構(gòu) 前 向 指 針 N 2 0 N個字節(jié)可用 后 向 指 針 N 2 0 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備

3、管理 linux教程第08課內(nèi)存與設(shè)備管理 設(shè)備驅(qū)動的分層結(jié)構(gòu) linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 linux教程第08課內(nèi)存與設(shè)備管理 設(shè)備驅(qū)動是Linux內(nèi)核的重要組成部分。驅(qū)動程序跟一般 的用戶應(yīng)用程序不同,它工作在內(nèi)核態(tài),編程方法和使用的 庫函數(shù)都跟用戶級的應(yīng)用程序有所區(qū)別。在Linux內(nèi)核中,設(shè) 備驅(qū)動跟文件系統(tǒng)聯(lián)系緊密。每一個設(shè)備都是作為一個設(shè)備 文件,交給文件系統(tǒng)去管理的。 設(shè)備驅(qū)動程序內(nèi)部是由一組函數(shù)組成的。函數(shù)由設(shè)備驅(qū) 動的上層文件系統(tǒng)來調(diào)用,每一個函數(shù)被稱做一個入口點(diǎn)。 入口點(diǎn)的集合被稱為設(shè)備驅(qū)動

4、程序的上半部分,實(shí)現(xiàn)設(shè)備驅(qū) 動與文件系統(tǒng)的接口。常用的入口點(diǎn)有:open、close(或 release)、read、write、ioctl等。 每一個函數(shù)的內(nèi)部實(shí)現(xiàn)被稱作驅(qū)動程序的下半部分,負(fù) 責(zé)實(shí)現(xiàn)具體的設(shè)備操作。函數(shù)的內(nèi)部實(shí)現(xiàn)通常是靠系統(tǒng)調(diào)用 提供的函數(shù)實(shí)現(xiàn)的,不能使用平常我們使用的用戶級的C語 言庫函數(shù)。 linux教程第08課內(nèi)存與設(shè)備管理 Linux通過設(shè)備號來區(qū)分不同的設(shè)備。設(shè)備號由兩部分組成: 主設(shè)備號MAJOR和次設(shè)備號MINOR。 主設(shè)備號MAJOR指明對應(yīng)哪些設(shè)備驅(qū)動。一般一個主設(shè)備號 對應(yīng)一個驅(qū)動程序。 次設(shè)備號MINOR用來區(qū)分同一個驅(qū)動程序控制下的不同的獨(dú) 立的設(shè)備

5、。 例如:硬盤的主設(shè)備名稱為hd。在/dev目錄下hd即為硬盤。 /dev/hda、/dev/hdb等是系統(tǒng)的第一個硬盤和第二個硬盤。而 hda0和hda1分別是第一個硬盤上的第一個分區(qū)和第二個分區(qū)。 /proc/devices列出所有現(xiàn)在正在使用的設(shè)備號。 linux教程第08課內(nèi)存與設(shè)備管理 Linux操作系統(tǒng)將所有的設(shè)備全部看成文件,并通過文件的操 作界面進(jìn)行操作,用戶程序可以像對其他文件一樣對此設(shè)備文 件進(jìn)行操作。這意味著: 由于每一個設(shè)備至少由文件系統(tǒng)的一個文件代表,因而都 有一個“文件名”。 應(yīng)用程序通??梢酝ㄟ^系統(tǒng)調(diào)用open()打開設(shè)備文件,建立 起與目標(biāo)設(shè)備的連接。 打開了代

6、表著目標(biāo)設(shè)備的文件,即建立起與設(shè)備的連接后, 可以通過read()、write()、ioctl()等常規(guī)的文件操作對目標(biāo)設(shè)備進(jìn) 行操作。 設(shè)備文件的屬性由三部分信息組成:第一部分是文件的類型, 第二部分是一個主設(shè)備號,第三部分是一個次設(shè)備號。其中類 型和主設(shè)備號結(jié)合在一起惟一地確定了設(shè)備文件驅(qū)動程序及其 界面,而次設(shè)備號則說明目標(biāo)設(shè)備是同類設(shè)備中的第幾個。 linux教程第08課內(nèi)存與設(shè)備管理 設(shè)備文件不能用普通的辦法建立。要通過mknod命令。 mknod命令的語法: mknod 路徑 模式 主設(shè)備號 次設(shè)備號 模式有兩種:c為字符設(shè)備 b為塊設(shè)備 例如:mknod /dev/test c

7、254 0 設(shè)備文件可以象普通文件一樣直接使用,例如: /dev/lp0為一個打印機(jī),使用cat doc.txt/dev/lp0就可以將文 檔交給打印機(jī)去進(jìn)行打印 /dev/ttyS0為主機(jī)上的串口COM1,使用讀寫文件的方法,也 可以實(shí)現(xiàn)對串口的讀寫操作 linux教程第08課內(nèi)存與設(shè)備管理 一、設(shè)備驅(qū)動中的關(guān)鍵數(shù)據(jù)結(jié)構(gòu) 二、驅(qū)動程序框架 三、實(shí)現(xiàn)各種功能的基本函數(shù) 四、實(shí)例 linux教程第08課內(nèi)存與設(shè)備管理 要編寫設(shè)備驅(qū)動程序,就要實(shí)現(xiàn)它跟高層文件系統(tǒng)和底層 硬件之間的操作接口。這些接口一般要遵循DDI/DKI (Device-Driver Interface / Device-Ker

8、nel Interface)接口規(guī) 范,所以要使用一些標(biāo)準(zhǔn)的數(shù)據(jù)結(jié)構(gòu)來進(jìn)行操作。 底層硬件的操作主要由不同硬件的特性來決定。跟文件系 統(tǒng)的接口主要使用三個數(shù)據(jù)結(jié)構(gòu): inode文件索引節(jié)點(diǎn)結(jié)構(gòu) struct file文件結(jié)構(gòu) 文件操作結(jié)構(gòu),設(shè)備驅(qū)動程序要實(shí)現(xiàn)這個結(jié)構(gòu)里的主要操 作 linux教程第08課內(nèi)存與設(shè)備管理 struct inode稱做索引節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu),定義如下: struct inode struct list_head i_hash; struct list_head i_list; struct list_head i_dentry; struct list_head i_di

9、rty_buffers; struct list_head i_dirty_data_buffers; unsigned longi_ino; atomic_ti_count; kdev_ti_dev; umode_ti_mode; nlink_ti_nlink; uid_ti_uid; gid_ti_gid; kdev_ti_rdev; loff_ti_size; time_ti_atime; time_ti_mtime; time_ti_ctime; unsigned inti_blkbits; unsigned longi_blksize; unsigned longi_blocks;

10、unsigned longi_version; struct semaphorei_sem; struct semaphorei_zombie; struct inode_operations*i_op; struct *i_fop;/文件操作指針文件操作指針 struct super_block*i_sb; wait_queue_head_ti_wait; struct *i_flock; struct address_space*i_mapping; struct address_spacei_data; struct dquot*i_dquotMAXQUOTAS; struct list

11、_head i_devices; struct pipe_inode_info*i_pipe; struct block_device*i_bdev;/塊設(shè)備塊設(shè)備 struct char_device*i_cdev;/字符設(shè)備字符設(shè)備 unsigned longi_dnotify_mask; struct dnotify_struct*i_dnotify; unsigned longi_state; unsigned inti_flags; unsigned chari_sock; atomic_ti_writecount; unsigned inti_attr_flags; _u32i_g

12、eneration; union struct minix_inode_infominix_i; struct ext2_inode_infoext2_i; struct ext3_inode_infoext3_i; struct hpfs_inode_infohpfs_i; struct ntfs_inode_infontfs_i; struct msdos_inode_infomsdos_i; struct umsdos_inode_infoumsdos_i; struct iso_inode_info isofs_i; struct nfs_inode_info nfs_i; struc

13、t sysv_inode_infosysv_i; struct affs_inode_infoaffs_i; struct ufs_inode_info ufs_i; struct efs_inode_info efs_i; struct romfs_inode_inforomfs_i; struct shmem_inode_infoshmem_i; struct coda_inode_infocoda_i; struct smb_inode_info smbfs_i; struct hfs_inode_info hfs_i; struct adfs_inode_infoadfs_i; str

14、uct qnx4_inode_infoqnx4_i; struct reiserfs_inode_inforeiserfs_i; struct bfs_inode_info bfs_i; struct udf_inode_info udf_i; struct ncp_inode_info ncpfs_i; struct proc_inode_infoproc_i; struct socketsocket_i; struct usbdev_inode_info usbdev_i; struct jffs2_inode_infojffs2_i; void *generic_ip; u; ; lin

15、ux教程第08課內(nèi)存與設(shè)備管理 struct file主要用于與文件系統(tǒng)相關(guān)的設(shè)備驅(qū)動程序,可提供關(guān)于被打開的文件的信 息,定義如下: struct file struct list_headf_list; struct dentry*f_dentry; struct vfsmount *f_vfsmnt; struct *f_op; atomic_tf_count; unsigned int f_flags; mode_tf_mode; loff_tf_pos; unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; struct

16、 fown_structf_owner; unsigned intf_uid, f_gid; intf_error; unsigned longf_version; /* needed for tty driver, and maybe others */ void*private_data; /* preallocated helper kiobuf to speedup O_DIRECT */ struct kiobuf*f_iobuf; longf_iobuf_lock; ; linux教程第08課內(nèi)存與設(shè)備管理 struct struct module *owner; loff_t (

17、*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struc

18、t inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*

19、fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendpage) (struct file *, struct page *, int, si

20、ze_t, loff_t *, int); unsigned long (*get_unmapped_area)( struct file *, unsigned long, unsigned long, unsigned long, unsigned long ); ; 在用戶自己的驅(qū)動程序中,首先要根據(jù)驅(qū)動程序的功能,完成結(jié)構(gòu)中函數(shù)的實(shí)現(xiàn)。 不需要的函數(shù)接口可以直接在結(jié)構(gòu)中初始化為NULL。中的變量會在驅(qū)動程序初始化時, 注冊到系統(tǒng)內(nèi)部。每個進(jìn)程對設(shè)備的操作,都會根據(jù)主次設(shè)備號,轉(zhuǎn)換成對結(jié)構(gòu)的訪 問。 在設(shè)備驅(qū)動中,如果有需要的操作而本結(jié)構(gòu)中沒有提供的,統(tǒng)統(tǒng)交給ioctl函數(shù)實(shí)現(xiàn) linu

21、x教程第08課內(nèi)存與設(shè)備管理 Linux的設(shè)備驅(qū)動程序與外部的接口可以分為三部分: 驅(qū)動程序與內(nèi)核的接口:通過來完成 驅(qū)動程序與系統(tǒng)引導(dǎo)的接口:利用驅(qū)動程序?qū)υO(shè)備初始化 驅(qū)動程序與設(shè)備的接口:描述了驅(qū)動程序如何與設(shè)備進(jìn)行 交互,這部分與具體設(shè)備密切相關(guān) 驅(qū)動程序的代碼可以分成以下幾個部分: 驅(qū)動程序的注冊和注銷; 設(shè)備的打開和釋放; 設(shè)備的讀寫; 設(shè)備的控制; 設(shè)備的中斷和查詢。 linux教程第08課內(nèi)存與設(shè)備管理 1. 驅(qū)動程序的注冊和注銷: 驅(qū)動程序一般通過注冊的方式將自己的函數(shù)操作集與具體 的設(shè)備關(guān)聯(lián)起來。所以,在設(shè)備初始化時,應(yīng)向系統(tǒng)進(jìn)行登 記register。卸載設(shè)備的時候用unr

22、egister注銷。 字符設(shè)備和塊設(shè)備的注冊和注銷并不相同。字符設(shè)備的注 冊函數(shù)是: int register_chrdev(unsigned int major,const char *name,struct *fops) 卸載函數(shù)是: int unregister_chrdev(unsigned int major,const char *name) linux教程第08課內(nèi)存與設(shè)備管理 Linux對字符設(shè)備的管理是通過一個字符設(shè)備表chrdevs 來 實(shí)現(xiàn)的。表里的每一項(xiàng)是一個device_struct結(jié)構(gòu)。 struct device_struct const char *name;

23、struct *fops; chrdevs 的數(shù)組下標(biāo)就是字符設(shè)備的主設(shè)備號major。 要查看系統(tǒng)中這個表格的當(dāng)前內(nèi)容,看/proc/devices即可。 linux教程第08課內(nèi)存與設(shè)備管理 字符設(shè)備的注冊:向chrdevs 中增加一個新項(xiàng)。 int register_chrdev(int major,char *name,struct *fops) major為申請的主設(shè)備號,為0時,自動尋找一個空閑號分 配。name為設(shè)備的名字。fops為驅(qū)動程序中結(jié)構(gòu)的指針。 注冊成功時,返回申請到的主設(shè)備號。出錯時返回一個負(fù) 值。 字符設(shè)備的注銷: void unregister_chrdev(i

24、nt major,char *name) linux教程第08課內(nèi)存與設(shè)備管理 2. 設(shè)備讀寫: 設(shè)備讀寫是實(shí)現(xiàn)用戶空間和內(nèi)核空間的數(shù)據(jù)交換,因此涉 及內(nèi)存操作。 設(shè)備驅(qū)動程序在申請和釋放內(nèi)存時,因?yàn)槭褂玫氖莾?nèi)核空 間,不能調(diào)用用戶空間的函數(shù)malloc和free,而代之以調(diào)用 kmalloc和kfree,它們在linux/kernel.h中被定義為: void *kmalloc(unsigned int len, int priority); void kfree(void * obj); 參數(shù)len為希望申請的字節(jié)數(shù),obj為要釋放的內(nèi)存指針。 priority為分配內(nèi)存操作的優(yōu)先級,即在

25、沒有足夠空閑內(nèi)存時 如何操作,一般由取值GFP_KERNEL解決即可。 linux教程第08課內(nèi)存與設(shè)備管理 2. 設(shè)備讀寫: 設(shè)備讀寫是實(shí)現(xiàn)用戶空間和內(nèi)核空間的數(shù)據(jù)交換,因此涉 及內(nèi)存操作。 內(nèi)存間數(shù)據(jù)的傳送: unsigned long copy_to_user(void *to,void *from,long count); unsigned long copy_from_user(void *to,void *from,long count); 以上兩個函數(shù)的原型在 linux教程第08課內(nèi)存與設(shè)備管理 3. 設(shè)備控制: 對設(shè)備的控制是通過對I/O端口的讀寫來實(shí)現(xiàn)的。 inline u

26、nsigned int inb(unsigned short port); inline unsigned int inb_p(unsigned short port);/讀端口 inline void outb(char value,unsigned short port); inline void outb_p(char value,unsigned short port); /寫端口 int _check_region(struct resource *parent, unsigned long start, unsigned long n);/檢查一個區(qū)域的端口 struct reso

27、urce *_request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name);/ 申請一個區(qū)域的端口 void _release_region(struct resource *parent, unsigned long start, unsigned long n);/釋放一個區(qū)域的端口 linux教程第08課內(nèi)存與設(shè)備管理 3. 設(shè)備控制: 對設(shè)備的控制接口通過ioctl函數(shù)來實(shí)現(xiàn)。它就象個大雜物箱,把跟設(shè)備有 關(guān)的各種操作都裝在這里。 例如:一個LCD的驅(qū)動,要

28、實(shí)現(xiàn)清屏LCD_Clear、顯示矩形Disp_Rect、 畫線Draw_Line等功能。 void LCD_Clear() void Disp_Rect() void Draw_Line static int *_ioctl(struct inode *inode, struct file *file, int cmd, long arg) switch(cmd) case:CLEAR LCD_Clear(); case:RECT Disp_Rect(); case:LINE Draw_Line(); linux教程第08課內(nèi)存與設(shè)備管理 編寫一個test.c,雖然它基本上什么也不干,但是它體

29、現(xiàn)了一個字符設(shè) 備驅(qū)動程序的基本框架: #define _NO_VERSION_ #include #include #include #include #include #include #include #include #include #include unsigned int test_major = 0;/用一個靜態(tài)變量存儲設(shè)備號 linux教程第08課內(nèi)存與設(shè)備管理 read和write的實(shí)現(xiàn): static sszie_t read_test(struct file * *buf,size_t count,loff_t *fops) copy_to_user(*buf,*); static sszie_t write_test(struct file * *buf,size_t count,loff_t *fops) copy_from_user(*file,*buf,coun

溫馨提示

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

評論

0/150

提交評論