Determine the Starting Point of Absolute Path

Một phần của tài liệu The art of linux kernel design (Trang 182 - 187)

4. Creation and Execution of Process 2 165

4.1 Open the Terminal Device File and Copy the File Handle

4.1.1 Open the Standard Input Device File

4.1.1.2 Determine the Starting Point of Absolute Path

The kernel calls open_namei to acquire the i node of the standard input device file as shown below:

//code path:fs/open.c:

int sys_open(const char * filename,int flag,int mode) {

struct m_inode * inode;

struct file * f;

int i,fd;

mode &=0777 & ~current->umask;

for(fd=0 ; fd<NR_OPEN ; fd++) //parse the filp of process 1

if (!current->filp[fd]) //get an idle item and fd is the number break;

if (fd>=NR_OPEN)//return when filp has no more idle item return -EINVAL;

current->close_on_exec &= ~(1<<fd);

f=0+file_table;//get the initial address of file_table[64]

for (i=0 ; i<NR_FILE ; i++,f++) //parse the file_table[64]

if (!f->f_count) break; //f is the pointer of the idle item if (i>=NR_FILE)//

return -EINVAL;

(current->filp[fd]=f)->f_count++; //mount filp to file_table and //increase the citation number if ((i=open_namei(filename,flag,mode,&inode))<0) {//get the i node

current->filp[fd]=NULL;

f->f_count=0;

return i;

}

……

}

//code path:fs/open.c:

int sys_open(const char * filename,int flag,int mode) {

struct m_inode * inode;

struct file * f;

int i,fd;

mode &=0777 & ~current->umask;

for(fd=0 ; fd<NR_OPEN ; fd++) if (!current->filp[fd])

break;

if (fd>=NR_OPEN) return -EINVAL;

The object can be satisfied by analyzing the name of the path continuously. The first stage of the analysis is to get the topmost i node by calling dir_namei, that is, the i node of the directory file dev in/dev/tty0. The second stage is to call find_entry to find the tty0 directory item and get the i node of tty0.

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) {//filename is //the pointer of/dev/tty0

current->filp[fd]=NULL;

f->f_count=0;

return i;

}

……

}

Kernel

Enable interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

The page that task_struct of process 1 resides task_struct of

process 1 Kernel code area Kernel data area

sys_open filp[20]

Process status

Process 0 Process 1

Interruptible Ready

Current process file_table[64]

ROM BIOS and VGA

Figure 4.2 Preparation for the open terminal device file.

The code for calling dir_namei is as follows:

The function dir_namei() will call get_dir() to get the topmost i node first and then acquires the address of tty0 and the length of the file name by parsing the name of the path. The code for calling get_dir is as follows:

//code path:fs/namei.c:

int open_namei(const char * pathname, int flag, int mode,

struct m_inode ** res_inode)//pathname is the pointer of /dev/tty0 {

const char * basename;//basename records the address of ’/’ in front int inr,dev,namelen;//namelen records the name length

struct m_inode * dir, *inode;

struct buffer_head * bh;

struct dir_entry * de;//de points to the directory content if ((flag & O_TRUNC) && !(flag & O_ACCMODE))

flag | = O_WRONLY;

mode &= 0777 & ~current->umask;

mode |= I_REGULAR;

if (!(dir = dir_namei(pathname,&namelen,&basename)))//get topmost i node return -ENOENT;

if (!namelen) { /* special case: ‘/usr/’ etc */

if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {

*res_inode=dir;

return 0;

}

iput(dir);

return -EISDIR;

}

bh = find_entry(&dir,basename,namelen,&de); //find the directory through //topmost i node

……

}

//code path:fs/namei.c:

static struct m_inode * dir_namei(const char * pathname, //pathname is the //pointer of //“/dev/tty0”

int * namelen, const char ** name) {

char c;

const char * basename;

struct m_inode * dir;

if (!(dir = get_dir(pathname))) //execution function of get i node return NULL;

basename = pathname;

while (c = get_fs_byte(pathname++))

//traverse the characters of/dev/tty0 and copy each one to c till the end

It is noteworthy that get_fs_byte is the core function of path resolution, which would extract the string in the path name one by one. This function will be used to analyze the path later. Its internal process is as follows:

Get_dir() will determine the absolute starting point of the path first, namely, whether the first character of “/dev/tty0” is “/” or not, if yes, it means that it is the abso- lute path name. Get_dir() starts searching files from the root i node, which is loaded in the kernel when loading root file system in Section 3.3.3 and is determined as the absolute starting point of the path. At the same time, the citation count of the root i node will increase. The code is as follows:

if (c==’/’) basename=pathname;

*namelen = pathname-basename-1;//determine the name length of tty0

*name = basename;//get the address of ’/’ in front of tty0 return dir;

}

//code path:include/asm/Segment.h:

extern inline unsigned char get_fs_byte(const char * addr) {

unsigned register char _v;

__asm__ (“movb%%fs:%1,%0” //movb could move 1 byte data to specific //register

:”=r” (_v)//v is the output character

:”m” (*addr));//*addr is the memory address to input return _v;

}

//code path:fs/namei.c:

static struct m_inode * get_dir(const char * pathname) //pathname is //the pointer //of “/dev/tty0”

{

char c;

const char * thisname;

struct m_inode * inode;

struct buffer_head * bh;

int namelen,inr,idev;

struct dir_entry * de;

Figure 4.3 shows how to locate the starting point of the path.

if (!current->root || !current->root->i_count)//root i node of //current process doesn’t exist or citation number is 0, the kernel //breaks

panic(“No root inode”);

if (!current->pwd || !current->pwd->i_count)

//root i node of current directory in current process doesn’t //exist or citation number is 0, the kernel breaks.

panic(“No cwd inode”);

if ((c=get_fs_byte(pathname))==’/’) {//it identifies that the //first character of “/dev/tty0” is ’/’

inode = current->root;

pathname++;

} else if I

inode = current->pwd;

else

return NULL; /* empty name is bad */

inode->i_count++;//the citation count of this i node increases by 1

……

}

Kernel

ROM BIOS

and VGA Enable

interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Kernel code area Kernel data area

get_dir

dir_namei open_namei i node_table[32]

Set root i node as starting point Process status

Process 0 Process 1

Interruptible Ready

Current process

Figure 4.3 Preparation for analyzing the file name.

Một phần của tài liệu The art of linux kernel design (Trang 182 - 187)

Tải bản đầy đủ (PDF)

(524 trang)