Linux file System (VII)---system invoke open operation (i)

Source: Internet
Author: User
Tags goto readable


(Kernel 2.4.37)


One

When we open a file, we need to get the file descriptor (previously said is the file array subscript), usually through the function open to complete, this system call in the <unistd.h> header file declaration definition, we look at the source:

530 Static inline long open (const char * name, int mode, int flags) 531 {532         return Sys_open (name, mode, flags); 533}

Ps: For these parameters generally we are very familiar with, often use, here by the way memory:

mode: parameters are optional:

#define S_IRWXU 00700     file owner readable writable executable #define S_IRUSR 00400 file owner readable     #define S_IWUSR 00200     file owner can write #de Fine s_ixusr 00100     file owner executable  #define S_IRWXG 00070     file user group writable readable executable #define S_IRGRP 00040     file user group readable 39 # Define S_IWGRP 00020     file user Group writable #define S_IXGRP 00010     file user Group executable  #define S_IRWXO 00007 Other user writable and readable     executable 4 3 #define S_iroth 00004     Other users can read #define S_iwoth 00002 other users can     write #define S_ixoth 00001     other users can execute

flags: defined in fcntl.h

 7 #define O_RDONLY 8 #define O_WRONLY 9 #define O_rdwr #define O_CREAT 0100/* Not FCNTL */one #define O_EXCL 0200 */Not FCNTL */#def          INE O_noctty 0400 * * not FCNTL */#define O_TRUNC 01000/Not FCNTL */#define O_append 02000 #define O_nonblock 04000 #define O_ndelay o_nonblock #define O_sync 010000 #de Fine Fasync 020000/* fcntl, for BSD compatibility * * #define O_DIRECT 040000/* DIRECT disk access H int * * #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000/* Must be a DIRECTORY * * #define O_nofoll OW 0400000/* don ' t follow links */
O_rdonly opening a file as read-only
O_wronly opening a file as a write-only method
O_rdwr opening a file in read and write mode
The above three can only select one, the following may be reasonable any combination:
O_creat Open File, if file does not exist then build file
O_EXCL Force open () fails if o_creat is already placed and the file exists
O_trunc truncate the length of the file to 0
O_append Force write () starts at the end of the file
For terminal files, the above four are invalid and provide two new flags:
O_noctty stop this terminal as a control terminal
O_nonblock causes open (), read (), write () to not be blocked.


we can see that the actual call in the Sys_open this system call, in fact, think is also very normal, for my system, there can be many groups of different file systems, for different file systems, the way to open the file is certainly not the same, All kernels need to invoke different functions to execute according to the specific file system type. Now look at the Sys_open function (FS/OPEN.C):

800 asmlinkage long Sys_open (const char * filename, int flags, int mode) 801 {802 char  * tmp;803 int fd, error;804 805 #if bits_per_long! = 32806 flags |= o_largefile;807 #endif808 tmp   = GetName (filename);  /* 1 */809 FD = PTR_ERR (tmp), 810 if (!IS_ERR (TMP)) {811 FD = GET_UNUSED_FD ();  /* 2 */812 if (FD >= 0) {813 struct file *f = Filp_open (TMP, flags, mode);/* 3                                 */814 error = Ptr_err (f); 815 if (Is_err (f)) 816    Goto out_error;817 Fd_install (FD, F); /* 4 */818}819 out:820 putname (TMP); 821}822 return fd;823 824 Out_error: 825 PUT_UNUSED_FD (FD); 826 fd = error;827 goto out;828} 

Mainly see the four steps of the above comment */* 1 */* 2 */* 3 */* 4 * /

/ * 1 */: This step is an auxiliary step to copy the filename from the user state to the kernel state variable. The basic steps involve several functions:

GetName char * (const char * filename) 126 {127         char *tmp, *result;128 129         result = Err_ptr (-ENOMEM);         = __getname ();     /* This thing is actually allocating kernel space in the user pack name */131         if (tmp)  {                 retval int = do_getname (filename, tmp);  /* The filename is actually copied to TMP */133 134                 result = tmp;135                 if (retval < 0) {136                         putname (TMP); 137                         result = Err_ptr (retval); 138                 }139         }140         return result;141}

Take a look at the __getname () function:

1099 #define __GETNAME ()     kmem_cache_alloc (Names_cachep, Slab_kernel)
is to allocate space in the kernel's slab space to accommodate the name ~ ~ ~


Take a look at the Do_getname () function:

104 Static Inline int do_getname (const char *filename, char *page), 106         int retval;107         unsigned long len = PATH _MAX;108 109         if ((unsigned long) filename >= task_size) {                 if (!segment_eq (Get_fs (), Kernel_ds)) 111                         return-efault;112         } else if (Task_size-(unsigned long) filename < Path_max) 113                 len = task_size-(unsigned l ONG) filename;114         retval = Strncpy_from_user ((char *) page, filename, len);/* A step in the core, The fact is to copy the filename to the space just allocated in the kernel */116         if (retval > 0) {117                 if (RetVal < len) 118                         return 0;119                 Return-enametoolong;120         } else if (!retval) 121                 retval =-enoent;122         return retval;123}

/ * 2 */: This step is required to find a file descriptor that is not used by FD

Take a look at this function get_unused_fd: Look at this link: get_unused_fd


/ * 3 */: Go back to see/* 3 */step, so far, we have found a usable file descriptor FD, then we have to do is to open the specified file, and then associate the FD and open file,/* 3 */ The step is to open the file we specified!

The following will refer to the name structure Nameidata, so look at this structure first:

Nameidata {701         struct dentry *dentry;   /* Current Directory Item object */702         struct vfsmount *mnt;    /* Mounted File system mount point */703         struct qstr last;        /* Path name the last part */704         unsigned int flags;      /* Query ID */705         int last_type;           /* The last part of the path name is type */706};

Look at this function Filp_open:

644/*645 * Note This while the flag value (low and bits) for Sys_open means:646 * 00-read-only647 * 01-w rite-only648 * 10-read-write649 * 11-special650 * It is changed into651 * 00-no permissions Neede d652 * 01-read-permission653 * 10-write-permission654 * 11-read-write655 * for the internal Routi NES (ie Open_namei ()/follow_link () etc).         XX is656 * Used by symlinks.657 */658 struct file *filp_open (const char * filename, int flags, int mode) 659 {660 int namei_flags, error;661 struct nameidata nd;662 663 namei_flags = flags;664 if ((namei_flags+1 ) & O_accmode) 665 namei_flags++;666 if (Namei_flags & O_trunc) 667 NAMEI_FL AGS |= 2;668/* Open file */669 error = Open_namei (filename, namei_flags, mode, &AMP;ND) based on file name; 670 if (! Error)/* Open this file below, this function returns a file struct pointer!!! */671 return Dentry_open (Nd.dentry, ND.MNT, FlaGS); 672 673 return err_ptr (Error); 674} 


This function is more complex, please see this link: Open_namei


Look back at this function, Dentry_open: This function returns the file struct pointer:

676 struct file *dentry_open (struct dentry *dentry, struct vfsmount *mnt, int flags) 677 {678 struct file * f;679 struct Inode *inode;680 static list_head (kill_list); 681 int error;682 683 error =-enfile;6    f = Get_empty_filp (); /* Get an empty file struct, if there is an error or insufficient memory, return 1error */685 if (!f) 686 Goto cleanup_dentry;687 F->f_flag   s = flags; /* Some assignment operations */688 F->f_mode = (flags+1) & o_accmode;689 inode = dentry->d_inode;                 /* Get the file Inode */690 if (F->f_mode & fmode_write) {691 error = get_write_access (inode); 692 if (error) 693 goto cleanup_file;694}695/* Some assignment operations */696 f-& Gt;f_dentry = Dentry;    /* Directory entry */697 f->f_vfsmnt = MNT;         /* mount point */698 f->f_pos = 0;       /* File relative start offset */699 f->f_reada = 0;   /* Pre-read flag */700 f->f_op = Fops_get (INODE-&GT;I_FOP); /* File Operationsfunction */701 File_move (f, &inode->i_sb->s_files);/* Enter the new file link into the file linked list of the Inode's corresponding super block */702 703/* PRE Allocate kiobuf for o_direct */704 f->f_iobuf = null;705 F->f_iobuf_lock = 0;706 if (f->f                 _flags & O_direct) {707 error = Alloc_kiovec (1, &AMP;F-&GT;F_IOBUF);/* Allocate IO buffer */708 if (Error) 709 goto cleanup_all;710}711 <span style= "White-space:pre" ></span&    Gt /* Below try to open the file, guaranteed to open this file normally */712 if (f->f_op && f->f_op->open) {713 error = F->         F_op->open (inode,f); 714 if (error) 715 goto cleanup_all;716}717 F->f_flags &= ~ (o_creat | O_excl | O_noctty |  O_TRUNC); 718 719 return F;  /* Returns the created file */720/* Below are all error handling */721 cleanup_all:722 if (f->f_iobuf) 723 Free_kiovec (1, &AMP;F-&GT;F_IOBUF); 724 Fops_put (f->f_OP) 725 if (F->f_mode & fmode_write) 726 put_write_access (inode); 727 File_move (F, & Amp;kill_list); /* Out of the "the". */728 F->f_dentry = null;729 f->f_vfsmnt = null;730 cleanup_file:731 Put_filp (f); 732 cleanup  _dentry:733 Dput (dentry); 734 Mntput (MNT); 735 return err_ptr (error); 736}737

Take a look at this function Get_empty_filp, get an empty file structure:

<span style= "FONT-SIZE:14PX;" > </span>26/* Find A unused file structure and return a pointer to it. * Returns NULL, if there is no more free file structures or * We run out of memory. * * Smp-safe.         +/-struct file * Get_empty_filp (void), {the static int old_max = 0; struct file * f; 36 37 File_list_lock ();                 if (Files_stat.nr_free_files > Nr_reserved_files) {/* If the number of allowed open has exceeded the system allowed */-used_one:40 f = list_entry (free_list.next, struct file, f_list); /* Delete one in free_list and leave it to the new file using */List_del (&f->f_list); files_stat.nr_free_files--; New_one:/* Create a new file structure below */memset (f, 0, sizeof (*f)); Atomic_set (&f->f_count,1); F->f_version = ++event; F->f_uid = current->fsuid; F->f_gid = current->fsgid; $ f->f_maxcount = Int_max; List_add (&f->f_list, &anon_list); Wuyi File_list_unlock ();   return F;         /* Return file */+ * * * * Use a reserved one if we ' re the Superuser 56 */57 if (files_stat.nr_free_files &&!current->euid), goto Used_one;  * * * Allocate A new one if we ' re below the limit.                 If you can also create a file struct, create a new one for OK. */Files_stat.nr_files < Files_stat.max_files {63 File_list_unlock ();  + F = kmem_cache_alloc (Filp_cachep, Slab_kernel); /* Assign a new file cache in Slab */file_list_lock (); if (f) {files_stat.nr_files++;/* qty +/-N          Ew_one; /* Initialize this new value */* * * * Big problems ... */PRINTK (kern_warning "VFS: Filp Allocation failed\n ");  (Files_stat.max_files > Old_max) {printk (kern_info Vfs:file-max limit%d) Reached\n ", files_stat.max_files); Old_max = Files_stat.max_files; File_list_unlock (); The return NULL; 79}


/* 4 */: Finally take a look at the Fd_install function, this function is relatively simple, is to apply the file descriptor FD and open file structure to associate:

<span style= "FONT-SIZE:14PX;"   > * * </span>74 * Install A file pointer in the FD array. * The VFS are full of places where we drop the files lock between * Setting the Open_fds bitmap and Installin  G The file in the file * array.  At any such point, we is vulnerable to a dup2 () race * Installing a file in the array before us. We need to detect this and Bayi * fput () The struct file we is about to overwrite in this case. * * * * * It should never happen-if we allow dup2 () does it, _really_ bad things * would follow. */fd_install (unsigned int fd, struct file * file), {files_struct *files = CURRENT-&G  T;files; /* Get the current process File open Table */Write_lock (&files->file_lock); if (FILES-&GT;FD[FD])/* If the file already exists under this FD, then error!  * * the BUG (); 94 FILES-&GT;FD[FD] = file;/* Associates This FD and the newly opened file */Write_unlock (&files->file_lock); 96}

At this point, the file open operation completed ~ ~ ~
















Linux file System (VII)---system invoke open operation (i)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.