先来想下,块设备涉及到什么,块设备属于IO设备,涉及到读写,与字符流设备不同的点就在于能够根据块来进行读写,仅取自己想要的块就OK,我们忽略块设备和字符流设备的区别,那么块设备作为IO设备,最重要的作用就是IO,即读写数据。体现到我们平常的使用则是read
write
,这些。学习块设备主要要学习的就两步,一是对于linux来说一切皆文件,那么一个文件的路径,是如何映射到块设备对应的块的,二是块设备上的数据是怎么与内存交互的,即怎么读进来的。
从源码开始,分析linux0.11的源码,从中梳理过程,带着上面我们提到的两个疑问,开始阅读代码
从open
开始
open
都清楚,打开一个文件,那么涉及到的就是文件与IO设备的映射关系。我们从fs/open.c的sys_open
函数说起:
fs/open.c1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
int sys_open(const char * filename, int flag, int mode) {
for(fd=0 ; fd<NR_OPEN ; fd++) if (!current->filp[fd]) break; if (fd>=NR_OPEN) return -EINVAL;
current->close_on_exec &= ~(1<<fd);
f=0+file_table; for (i=0 ; i<NR_FILE ; i++,f++) if (!f->f_count) break; if (i>=NR_FILE) return -EINVAL; (current->filp[fd]=f)->f_count++;
if ((i=open_namei(filename,flag,mode,&inode))<0) { current->filp[fd]=NULL; f->f_count=0; return i; } }
|
fs/namei.c1 2 3 4 5 6 7 8
| int open_namei(const char * pathname, int flag, int mode, struct m_inode ** res_inode) { if (!(dir = dir_namei(pathname,&namelen,&basename))) return -ENOENT; }
|
dir_namei1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| static struct m_inode * dir_namei(const char * pathname, int * namelen, const char ** name) { char c; const char * basename; struct m_inode * dir;
if (!(dir = get_dir(pathname))) return NULL; basename = pathname; while ((c=get_fs_byte(pathname++))) if (c=='/') basename=pathname; *namelen = pathname-basename-1; *name = basename; return dir; }
|
重点转移到了get_dir