Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the principle of open based on linux

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the relevant knowledge of "what is the principle of open based on linux". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

We all need to open before we manipulate a file. Let's take a look at how open performs roughly in a virtual file system. The specific process will not be analyzed. This paper mainly analyzes the implementation principle of virtual file system.

Asmlinkage int sys_open (const char * filename,int flags,int mode)

{

Char * tmp

Int error

Error = getname (filename, & tmp)

If (error)

Return error

Error = do_open (tmp,flags,mode)

Putname (tmp)

Return error

}

Here is the code for do_open.

/ / Open a file

Int do_open (const char * filename,int flags,int mode)

{

Struct inode * inode

Struct file * f

Int flag,error,fd

/ / find an available file descriptor

For (fd=0; fdfiles- > fd [fd])

Break

/ / No available one was found

If (fd > = NR_OPEN | | fd > = current- > rlimm [RLIMIT _ NOFILE] .rlim _ cur)

Return-EMFILE

/ / clear the close_on_exec tag bit

FD_CLR (fd,¤t- > files- > close_on_exec)

/ / get an available file structure

F = get_empty_filp ()

If (! F)

Return-ENFILE

/ / establish the mapping from fd to file structure

Current- > files- > fd [fd] = f

F-> f_flags = flag = flags

F-> f_mode = (flag+1) & O_ACCMODE

If (f-> f_mode)

Flag++

If (flag & (O_TRUNC | O_CREAT))

Flag | = 2

/ / find the inode node corresponding to the file and put it in the inode variable

Error = open_namei (filename,flag,mode,&inode,NULL)

If (! error & & (f-> f_mode & 2)) {

Error = get_write_access (inode)

If (error)

Iput (inode)

}

If (error) {

Current- > files- > fd [fd] = NULL

F.frankcountmuri-

Return error

}

/ / establish the mapping relationship between file structure and inode

F-> f_inode = inode

/ / initialize file offset

F-> f_pos = 0

F-> f_reada = 0

F-> f_op = NULL

/ / the function set of the file structure of the assignment operation

If (inode- > i_op)

F-> f_op = inode- > iComop-> default_file_ops

If (f-> f_op & & f-> flip-> open) {

/ / call the open function of the underlying file system

Error = f-> fopp-> open (inode,f)

If (error) {

If (f-> f_mode & 2) put_write_access (inode)

Iput (inode)

F.frankcountmuri-

Current- > files- > fd [fd] = NULL

Return error

}

}

F-> f_flags & = ~ (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC)

Return (fd)

}

The main job is to find the inode node corresponding to the file through open_namei, and then execute the underlying open. Finally, the relationship from fd to file to inode is established. In the virtual file system, super block, inode, directory and file are all abstract concepts, and the specific operation functions are implemented by each file system. So we first find a structure, and then call the operation function of the specific file system according to the actual operation value.

So let's first look at open_namei, and then look at the specific open function.

The following is the core code of open_namei.

/ / find out the inode of the last level directory

Error = dir_namei (pathname,&namelen,&basename,base,&dir)

/ / find the inode corresponding to a file in the last level directory

Error = lookup (dir,basename,namelen,&inode)

The general idea is to find the inode of the last level directory first, and then look for a file in the last level directory. Let's see how to find the inode corresponding to the last level of directory.

/ / find out the inode corresponding to the last level directory in pathname

Static int dir_namei (const char * pathname, int * namelen, const char * name

Struct inode * base, struct inode * * res_inode)

{

Char c

Const char * thisname

Int len,error

Struct inode * inode

* res_inode = NULL

/ / if no base is passed, the search starts from the current working directory of the process

If (! base) {

Base = current- > fs- > pwd

Base- > iSuppli countdown +

}

/ / absolute path, start from the root directory

If ((c = * pathname) = ='/') {

Iput (base)

Base = current- > fs- > root

Pathname++

Base- > iSuppli countdown +

}

/ / find out the inode node corresponding to the last level directory of pathname

While (1) {

Thisname = pathname

/ / split the part of the path with /. If you encounter /, you will get a certain level of path name. Thisname points to the first address of the current path, and len represents the corresponding length of this part of the path.

For (len=0; (c = * (pathname++)) & & (c! ='/'); len++)

/ * nothing * /

/ / c is empty to indicate that the last character, that is, the end of the path, is not looking for the last file or directory.

If (! C)

Break

Base- > iSuppli countdown +

/ / find a file in the base directory

Error = lookup (base,thisname,len,&inode)

If (error) {

Iput (base)

Return error

}

/ / set base to inode, and keep looking

Error = follow_link (base,inode,0,0,&base)

If (error)

Return error

}

If (! base- > i_op | |! base- > iPrep-> lookup) {

Iput (base)

Return-ENOTDIR

}

* name = thisname

* namelen = len

* res_inode = base

Return 0

}

It is by splitting the string with /, under the starting directory, that is, the root directory or the given directory. Find the inode of the next level directory and iterate over and over again to find the inode of the last level directory. We found that the lookup function is used to find the inode of the last level directory and the inode of a file in a certain directory. Let's take a look at his realization. Core code.

Return dir- > iPop-> lookup (dir,name,len,result)

Take the ext file system as an example. Look at the implementation of lookup.

Int ext_lookup (struct inode * dir,const char * name, int len)

Struct inode * * result)

{

Int ino

Struct ext_dir_entry * de

Struct buffer_head * bh

* result = NULL

If (! dir)

Return-ENOENT

If (! S_ISDIR (dir- > i_mode)) {

Iput (dir)

Return-ENOENT

}

If (! (bh = ext_find_entry (dir,name,len,&de,NULL,NULL) {

Iput (dir)

Return-ENOENT

}

Ino = de- > inode

Brelse (bh)

If (! (* result = iget (dir- > iSupplsbPhonino)) {

Iput (dir)

Return-EACCES

}

Iput (dir)

Return 0

}

Static struct buffer_head * ext_find_entry (struct inode * dir

Const char * name, int namelen, struct ext_dir_entry * * res_dir

Struct ext_dir_entry * * prev_dir, struct ext_dir_entry * * next_dir)

{

Long offset

Struct buffer_head * bh

Struct ext_dir_entry * de

* res_dir = NULL

If (! dir)

Return NULL

# ifdef NO_TRUNCATE

If (namelen > EXT_NAME_LEN)

Return NULL

# else

If (namelen > EXT_NAME_LEN)

Namelen = EXT_NAME_LEN

# endif

/ / read the file contents of the directory, and then compare

Bh = ext_bread (dir,0,0)

If (! bh)

Return NULL

If (prev_dir)

* prev_dir = NULL

If (next_dir)

* next_dir = NULL

Offset = 0

De = (struct ext_dir_entry *) bh- > b_data

While (offset

< dir->

I_size) {

If ((char *) de > = BLOCK_SIZE+bh- > b_data) {

Brelse (bh)

Bh = NULL

Bh = ext_bread (dir,offset > > BLOCK_SIZE_BITS,0)

If (! bh)

Continue

De = (struct ext_dir_entry *) bh- > b_data

If (prev_dir)

* prev_dir = NULL

}

If (de- > rec_len)

< 8 || de->

Rec_len% 8! = 0 | |

De- > rec_len

< de->

Name_len + 8 | |

(char *) de) + de- > rec_len-1 > = BLOCK_SIZE+bh- > b_data) {

Printk ("ext_find_entry: bad dir entry\ n")

Printk ("dev=%d, dir=%ld, offset=%ld, rec_len=%d, name_len=%d\ n"

Dir- > i_dev, dir- > i_ino, offset, de- > rec_len, de- > name_len)

De = (struct ext_dir_entry *) (bh- > b_data+BLOCK_SIZE)

Offset = (offset / BLOCK_SIZE) + 1) * BLOCK_SIZE

Continue

/ * brelse (bh)

Return NULL; * /

}

/ / whether the desired file has been found

If (ext_match (namelen,name,de)) {

* res_dir = de

If (next_dir)

If (offset + de- > rec_len)

< dir->

I_size & &

((char *) de) + de- > rec_len

< BLOCK_SIZE+bh->

B_data)

* next_dir = (struct ext_dir_entry *)

((char *) de + de- > rec_len)

Else

* next_dir = NULL

Return bh

}

Offset + = de- > rec_len

If (prev_dir)

* prev_dir = de

De = (struct ext_dir_entry *) ((char *) de + de- > rec_len)

}

Brelse (bh)

Return NULL

}

More code, you don't need to study, mainly to read the contents of the directory from the hard disk, and then traverse whether each file name is consistent with what you are looking for.

Through the above analysis, we have found a file corresponding to the inode node. The general file system does not implement the open function. So just return inode and establish a relationship from fd to file to inode. The subsequent operation on the file is also done through the set of operation functions of the inode node.

This is the end of the content of "what is the principle of open based on linux". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report