久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Linux文件系統(tǒng)(七)

 豆芽愛尚閱 2015-05-14


(內(nèi)核2.4.37)


一,、

當(dāng)我們打開一個文件的時候,,需要獲得文件的文件描述符(前面已經(jīng)說過其實就是文件數(shù)組下標(biāo)),,一般是通過函數(shù)open來完成,,這個系統(tǒng)調(diào)用在<unistd.h>頭文件中聲明定義,我們看一下源碼:

  1. 530 static inline long open(const char * name, int mode, int flags)  
  2. 531 {  
  3. 532         return sys_open(name, mode, flags);  
  4. 533 }  

Ps:對于這些參數(shù)一般我們都很熟悉,,經(jīng)常使用,,這里順便提出記憶一下:

mode:參數(shù)可選:

  1. 32 #define S_IRWXU 00700     文件所有者可讀可寫可執(zhí)行  
  2. 33 #define S_IRUSR 00400     文件所有者可讀  
  3. 34 #define S_IWUSR 00200     文件所有者可寫  
  4. 35 #define S_IXUSR 00100     文件所有者可執(zhí)行  
  5. 36   
  6. 37 #define S_IRWXG 00070     文件用戶組可寫可讀可執(zhí)行  
  7. 38 #define S_IRGRP 00040     文件用戶組可讀  
  8. 39 #define S_IWGRP 00020     文件用戶組可寫  
  9. 40 #define S_IXGRP 00010     文件用戶組可執(zhí)行  
  10. 41   
  11. 42 #define S_IRWXO 00007     其他用戶可寫可讀可執(zhí)行  
  12. 43 #define S_IROTH 00004     其他用戶可讀  
  13. 44 #define S_IWOTH 00002     其他用戶可寫  
  14. 45 #define S_IXOTH 00001     其他用戶可執(zhí)行  

flags:在fcntl.h中定義

  1.  7 #define O_RDONLY             00  
  2.  8 #define O_WRONLY             01  
  3.  9 #define O_RDWR               02  
  4. 10 #define O_CREAT            0100 /* not fcntl */  
  5. 11 #define O_EXCL             0200 /* not fcntl */  
  6. 12 #define O_NOCTTY           0400 /* not fcntl */  
  7. 13 #define O_TRUNC           01000 /* not fcntl */  
  8. 14 #define O_APPEND          02000  
  9. 15 #define O_NONBLOCK        04000  
  10. 16 #define O_NDELAY        O_NONBLOCK  
  11. 17 #define O_SYNC           010000  
  12. 18 #define FASYNC           020000 /* fcntl, for BSD compatibility */  
  13. 19 #define O_DIRECT         040000 /* direct disk access hint */  
  14. 20 #define O_LARGEFILE     0100000  
  15. 21 #define O_DIRECTORY     0200000 /* must be a directory */  
  16. 22 #define O_NOFOLLOW      0400000 /* don't follow links */  
O_RDONLY          以只讀方式打開文件
O_WRONLY         以只寫方式打開文件
O_RDWR              以讀和寫的方式打開文件
上面三個只能選擇一個,下面的可以合理的任意組合:
O_CREAT             打開文件,,如果文件不存在則建立文件
O_EXCL                如果已經(jīng)置O_CREAT且文件存在,,則強(qiáng)制open()失敗
O_TRUNC             將文件的長度截為0
O_APPEND           強(qiáng)制write()從文件尾開始
對于終端文件,上面四個是無效,,提供了兩個新的標(biāo)志:
O_NOCTTY           停止這個終端作為控制終端
O_NONBLOCK      使open(),、read()、write()不被阻塞,。


我們可以看到,,里面實際調(diào)用的是sys_open這個系統(tǒng)調(diào)用,其實想想也很正常,,對于我的一個系統(tǒng)而言,,可以存在很多組不同的文件系統(tǒng),對于不同的文件系統(tǒng),,打開文件的方式肯定是不一樣的,,所有內(nèi)核需要根據(jù)具體的文件系統(tǒng)的類型去調(diào)用不同的函數(shù)進(jìn)行執(zhí)行。現(xiàn)在看看sys_open函數(shù)(fs/open.c中):

  1. 800 asmlinkage long sys_open(const char * filename, int flags, int mode)  
  2. 801 {  
  3. 802         char * tmp;  
  4. 803         int fd, error;  
  5. 804   
  6. 805 #if BITS_PER_LONG != 32  
  7. 806         flags |= O_LARGEFILE;  
  8. 807 #endif  
  9. 808         tmp = getname(filename);   /* 1 */  
  10. 809         fd = PTR_ERR(tmp);  
  11. 810         if (!IS_ERR(tmp)) {  
  12. 811                 fd = get_unused_fd();  /* 2 */  
  13. 812                 if (fd >= 0) {  
  14. 813                         struct file *f = filp_open(tmp, flags, mode); /* 3 */  
  15. 814                         error = PTR_ERR(f);  
  16. 815                         if (IS_ERR(f))  
  17. 816                                 goto out_error;  
  18. 817                         fd_install(fd, f);    /* 4 */  
  19. 818                 }  
  20. 819 out:  
  21. 820                 putname(tmp);  
  22. 821         }  
  23. 822         return fd;  
  24. 823   
  25. 824 out_error:  
  26. 825         put_unused_fd(fd);  
  27. 826         fd = error;  
  28. 827         goto out;  
  29. 828 }  

主要看上面注釋表示的四大步驟/* 1 */  /* 2 */  /* 3 */  /* 4 */

/* 1 */:這步是一個輔助步驟,,將filename從用戶態(tài)拷貝到內(nèi)核態(tài)變量中,。基本步驟涉及一下幾個函數(shù):

  1. 125 char * getname(const char * filename)  
  2. 126 {  
  3. 127         char *tmp, *result;  
  4. 128   
  5. 129         result = ERR_PTR(-ENOMEM);  
  6. 130         tmp = __getname();     /* 這玩意吧其實是分配內(nèi)核中空間用戶裝name */  
  7. 131         if (tmp)  {  
  8. 132                 int retval = do_getname(filename, tmp);  /* 其實就是將filename拷貝到tmp中 */  
  9. 133   
  10. 134                 result = tmp;  
  11. 135                 if (retval < 0) {  
  12. 136                         putname(tmp);  
  13. 137                         result = ERR_PTR(retval);  
  14. 138                 }  
  15. 139         }  
  16. 140         return result;  
  17. 141 }  

看一下__getname()函數(shù):

  1. 1099 #define __getname()     kmem_cache_alloc(names_cachep, SLAB_KERNEL)  
就是在內(nèi)核的slab空間中分配能夠容納name的空間~~~


看一下do_getname()函數(shù):

  1. 104 static inline int do_getname(const char *filename, char *page)  
  2. 105 {  
  3. 106         int retval;  
  4. 107         unsigned long len = PATH_MAX;  
  5. 108   
  6. 109         if ((unsigned long) filename >= TASK_SIZE) {  
  7. 110                 if (!segment_eq(get_fs(), KERNEL_DS))  
  8. 111                         return -EFAULT;  
  9. 112         } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX)  
  10. 113                 len = TASK_SIZE - (unsigned long) filename;  
  11. 114   
  12. 115         retval = strncpy_from_user((char *)page, filename, len);/* 核心的一個步驟,,其實就是將filename拷貝到剛剛在內(nèi)核中分配的空間中 */  
  13. 116         if (retval > 0) {  
  14. 117                 if (retval < len)  
  15. 118                         return 0;  
  16. 119                 return -ENAMETOOLONG;  
  17. 120         } else if (!retval)  
  18. 121                 retval = -ENOENT;  
  19. 122         return retval;  
  20. 123 }  

/* 2 */:這一步是需要找到一個沒有使用的文件描述符fd

看一下這個函數(shù)get_unused_fd:看這個鏈接:get_unused_fd


/* 3 */:再回到上面看/* 3 */步驟,,到現(xiàn)在為止,,我們已經(jīng)找到了一個可用的文件描述符fd了,然后我們要做的就是打開指定文件,,然后將這個fd和打開的文件關(guān)聯(lián)即可,,/* 3 */步驟就是打開我們指定的文件!

下面會涉及到名字結(jié)構(gòu)nameidata,,所以先看看這個結(jié)構(gòu)體:

  1. 700 struct nameidata {  
  2. 701         struct dentry *dentry;   /* 當(dāng)前目錄項對象 */  
  3. 702         struct vfsmount *mnt;    /* 已安裝的文件系統(tǒng)掛載點 */  
  4. 703         struct qstr last;        /* 路徑名稱最后一部分 */  
  5. 704         unsigned int flags;      /* 查詢標(biāo)識 */  
  6. 705         int last_type;           /* 路徑名稱最后一部分類型 */  
  7. 706 };  

看這個函數(shù)filp_open:

  1. 644 /* 
  2. 645  * Note that while the flag value (low two bits) for sys_open means: 
  3. 646  *      00 - read-only 
  4. 647  *      01 - write-only 
  5. 648  *      10 - read-write 
  6. 649  *      11 - special 
  7. 650  * it is changed into 
  8. 651  *      00 - no permissions needed 
  9. 652  *      01 - read-permission 
  10. 653  *      10 - write-permission 
  11. 654  *      11 - read-write 
  12. 655  * for the internal routines (ie open_namei()/follow_link() etc). 00 is 
  13. 656  * used by symlinks. 
  14. 657  */  
  15. 658 struct file *filp_open(const char * filename, int flags, int mode)  
  16. 659 {  
  17. 660         int namei_flags, error;  
  18. 661         struct nameidata nd;  
  19. 662   
  20. 663         namei_flags = flags;  
  21. 664         if ((namei_flags+1) & O_ACCMODE)  
  22. 665                 namei_flags++;  
  23. 666         if (namei_flags & O_TRUNC)  
  24. 667                 namei_flags |= 2;  
  25. 668         /* 根據(jù)文件名打開文件 */  
  26. 669         error = open_namei(filename, namei_flags, mode, &nd);  
  27. 670         if (!error)   /* 下面打開這個文件,,這個函數(shù)返回的是file結(jié)構(gòu)體指針!??! */  
  28. 671                 return dentry_open(nd.dentry, nd.mnt, flags);  
  29. 672   
  30. 673         return ERR_PTR(error);  
  31. 674 }  


這個函數(shù)比較復(fù)雜,請看這個鏈接:open_namei


回頭再看這個函數(shù),,dentry_open:這個函數(shù)返回的file結(jié)構(gòu)體指針:

  1. 676 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)  
  2. 677 {  
  3. 678         struct file * f;  
  4. 679         struct inode *inode;  
  5. 680         static LIST_HEAD(kill_list);  
  6. 681         int error;  
  7. 682   
  8. 683         error = -ENFILE;  
  9. 684         f = get_empty_filp();    /* 得到一個空的file結(jié)構(gòu)體,,如果出錯或者內(nèi)存不足,返回1error */  
  10. 685         if (!f)  
  11. 686                 goto cleanup_dentry;  
  12. 687         f->f_flags = flags;   /* 一些賦值操作 */  
  13. 688         f->f_mode = (flags+1) & O_ACCMODE;  
  14. 689         inode = dentry->d_inode; /* 獲得文件inode */  
  15. 690         if (f->f_mode & FMODE_WRITE) {  
  16. 691                 error = get_write_access(inode);  
  17. 692                 if (error)  
  18. 693                         goto cleanup_file;  
  19. 694         }  
  20. 695         /* 一些賦值操作 */  
  21. 696         f->f_dentry = dentry; /* 目錄項 */  
  22. 697         f->f_vfsmnt = mnt;    /* 掛載點 */  
  23. 698         f->f_pos = 0;         /* 文件相對開頭偏移 */  
  24. 699         f->f_reada = 0;       /* 預(yù)讀標(biāo)志 */  
  25. 700         f->f_op = fops_get(inode->i_fop);   /* 文件操作函數(shù) */  
  26. 701         file_move(f, &inode->i_sb->s_files);/* 將新建的file鏈接進(jìn)入inode對應(yīng)的超級塊的file鏈表中 */  
  27. 702   
  28. 703         /* preallocate kiobuf for O_DIRECT */  
  29. 704         f->f_iobuf = NULL;  
  30. 705         f->f_iobuf_lock = 0;  
  31. 706         if (f->f_flags & O_DIRECT) {  
  32. 707                 error = alloc_kiovec(1, &f->f_iobuf); /* 分配io buffer */  
  33. 708                 if (error)  
  34. 709                         goto cleanup_all;  
  35. 710         }  
  36. 711 <span style="white-space:pre">    </span>    /* 下面嘗試打開文件,,保證能夠正常打開這個文件 */  
  37. 712         if (f->f_op && f->f_op->open) {   
  38. 713                 error = f->f_op->open(inode,f);  
  39. 714                 if (error)  
  40. 715                         goto cleanup_all;  
  41. 716         }  
  42. 717         f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);  
  43. 718   
  44. 719         return f;  /* 返回創(chuàng)建好的file */  
  45. 720         /* 下面都是出錯處理 */  
  46. 721 cleanup_all:  
  47. 722         if (f->f_iobuf)  
  48. 723                 free_kiovec(1, &f->f_iobuf);  
  49. 724         fops_put(f->f_op);  
  50. 725         if (f->f_mode & FMODE_WRITE)  
  51. 726                 put_write_access(inode);  
  52. 727         file_move(f, &kill_list); /* out of the way.. */  
  53. 728         f->f_dentry = NULL;  
  54. 729         f->f_vfsmnt = NULL;  
  55. 730 cleanup_file:  
  56. 731         put_filp(f);  
  57. 732 cleanup_dentry:  
  58. 733         dput(dentry);  
  59. 734         mntput(mnt);  
  60. 735         return ERR_PTR(error);  
  61. 736 }  
  62. 737   

看一下這個函數(shù)get_empty_filp,,得到一個空的file結(jié)構(gòu)體:

  1. <span style="font-size:14px;"> </span>26 /* Find an unused file structure and return a pointer to it. 
  2.  27  * Returns NULL, if there are no more free file structures or 
  3.  28  * we run out of memory. 
  4.  29  * 
  5.  30  * SMP-safe. 
  6.  31  */  
  7.  32 struct file * get_empty_filp(void)  
  8.  33 {  
  9.  34         static int old_max = 0;  
  10.  35         struct file * f;  
  11.  36   
  12.  37         file_list_lock();  
  13.  38         if (files_stat.nr_free_files > NR_RESERVED_FILES) {  /* 如果允許打開的數(shù)量已經(jīng)超過系統(tǒng)允許的 */  
  14.  39         used_one:  
  15.  40                 f = list_entry(free_list.next, struct file, f_list); /* 在free_list中刪除一個,留下了給新的file使用 */  
  16.  41                 list_del(&f->f_list);  
  17.  42                 files_stat.nr_free_files--;  
  18.  43         new_one: /* 下面創(chuàng)建一個新的file結(jié)構(gòu)體 */  
  19.  44                 memset(f, 0, sizeof(*f));  
  20.  45                 atomic_set(&f->f_count,1);  
  21.  46                 f->f_version = ++event;  
  22.  47                 f->f_uid = current->fsuid;  
  23.  48                 f->f_gid = current->fsgid;  
  24.  49                 f->f_maxcount = INT_MAX;  
  25.  50                 list_add(&f->f_list, &anon_list);  
  26.  51                 file_list_unlock();  
  27.  52                 return f;   /* 返回file */  
  28.  53         }  
  29.  54         /* 
  30.  55          * Use a reserved one if we're the superuser 
  31.  56          */  
  32.  57         if (files_stat.nr_free_files && !current->euid)  
  33.  58                 goto used_one;  
  34.  59         /* 
  35.  60          * Allocate a new one if we're below the limit.  如果還可以創(chuàng)建file結(jié)構(gòu)體,,那么創(chuàng)建一個新的就OK 
  36.  61          */  
  37.  62         if (files_stat.nr_files < files_stat.max_files) {  
  38.  63                 file_list_unlock();  
  39.  64                 f = kmem_cache_alloc(filp_cachep, SLAB_KERNEL);  /* 在slab中分配一個新的file緩存 */  
  40.  65                 file_list_lock();  
  41.  66                 if (f) {  
  42.  67                         files_stat.nr_files++; /* 數(shù)量++ */  
  43.  68                         goto new_one;          /* 初始化這個新的值 */  
  44.  69                 }  
  45.  70                 /* Big problems... */  
  46.  71                 printk(KERN_WARNING "VFS: filp allocation failed\n");  
  47.  72   
  48.  73         } else if (files_stat.max_files > old_max) {  
  49.  74                 printk(KERN_INFO "VFS: file-max limit %d reached\n", files_stat.max_files);  
  50.  75                 old_max = files_stat.max_files;  
  51.  76         }  
  52.  77         file_list_unlock();  
  53.  78         return NULL;  
  54.  79 }  


/* 4 */:最后看一下fd_install函數(shù),,這個函數(shù)比較簡單,就是將之前申請的文件描述符fd和打開的文件file結(jié)構(gòu)體關(guān)聯(lián)起來:

  1. <span style="font-size:14px;"> </span>74 /* 
  2.  75  * Install a file pointer in the fd array.   
  3.  76  * 
  4.  77  * The VFS is full of places where we drop the files lock between 
  5.  78  * setting the open_fds bitmap and installing the file in the file 
  6.  79  * array.  At any such point, we are vulnerable to a dup2() race 
  7.  80  * installing a file in the array before us.  We need to detect this and 
  8.  81  * fput() the struct file we are about to overwrite in this case. 
  9.  82  * 
  10.  83  * It should never happen - if we allow dup2() do it, _really_ bad things 
  11.  84  * will follow. 
  12.  85  */  
  13.  86   
  14.  87 void fd_install(unsigned int fd, struct file * file)  
  15.  88 {  
  16.  89         struct files_struct *files = current->files;  /* 獲得當(dāng)前進(jìn)程文件打開表 */  
  17.  90             
  18.  91         write_lock(&files->file_lock);  
  19.  92         if (files->fd[fd])   /* 如果這個fd下已經(jīng)存在文件了,,那么error,! */  
  20.  93                 BUG();   
  21.  94         files->fd[fd] = file;/* 關(guān)聯(lián)這個fd和新打開的文件 */  
  22.  95         write_unlock(&files->file_lock);  
  23.  96 }  

至此,文件open操作完成了~~~
















    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多