inux学习之文件系统篇(二)

文件系统(二)

1.目录操作

mkdir

#include<sys/stat.h>

#include<sys/types.h>

int mkdir(const char *pathname,mode_t mode);

创建一个目录

rmdir

 #include<unistd.h>

int rmdir(const char *pathname);

删除一个目录

opendir/fdopendir

 #include<sys/types.h>

#include<dirent.h>

DIR *opendir(const char *name);

DIR *fdopendir(int fd);

打开一个目录

 readdir

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

struct dirent   
{   
  long d_ino; /* inode number 索引节点号 */  
     
    off_t d_off; /* offset to this dirent 在目录文件中的偏移 */  
     
    unsigned short d_reclen; /* length of this d_name 文件名长 */  
     
    unsigned char d_type; /* the type of d_name 文件类型 */  
     
    char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */

 readdir每次返回一条记录项,DIR* 指针指向下一条记录项。

 rewinddir

 #include<sys/types.h>

#include <dirent.h>

void rewinddir(DIR *dirp);

把目录指针恢复到目录的起始位置

telldir/seekdir

#include<dirent.h>

long telldir(DIR *dirp);

#include <dirent.h>

void seekdir(DIR *dirp,long offset);

 closedir

 #include<sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

练习:递归遍历目录(实现tree命令)

#include<stdio.h>  
#include <errno.h>  
#include<stdlib.h>  
#include<string.h>  
#include <dirent.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <unistd.h>  
  
#define MAX_PATH 512  
  void dirwalk(char *dir,void(*fcn)(char *))  
{  
    DIR *dfd;  
    char name[MAX_PATH];  
    struct dirent *dp;  
if ((dfd = opendir(dir)) == NULL) { fprintf(stderr,"dir_walk: can't open %s %s", dir); return; } while ((dp = readdir(dir)) != NULL) { if (strcmp(dp->d_name, ".") == 0||strcmp(dp->d_name,".."==0) continue; /* 跳过当前目录和上一层目录以及隐藏文件*/ if (strlen(pathname) + strlen(dp->d_name) + 2 > sizeof(name)) { fprintf(stderr,"dir_order: name %s %s too long ", dir, dp->d_name); }
else { memset(name, 0, sizeof(name)); sprintf(name, "%s/%s", dir, dp->d_name); (*fcn)(name); } } closedir(dfd); } void fsize(char *name) { struct stat stbuf; if (stat(name, &stbuf) == -1) { fprintf(stderr,"fsize:can't access %s ", name); return; } if ((stbuf.st_mode & S_IFMT) == S_IFDIR) //与后留下文件类型,若==S_IFDIR表示是一个目录 { dirwalk(name,fsize); } printf("%s %8ld ", stbuf.st_size, name); } int main(int argc, char **argv) { if (argc == 1) /*default:current directory /.app*/ { fsize("."); }
else
while(--argc>0) { fsize(*++argv);
} return 0; }

2.VFS虚拟文件系统

  Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等。通过使用同一套文件 I/O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式;更进一步,对文件的 操作可以跨文件系统而执行。我们可以使用 cp 命令从 vfat 文件系统格式的硬盘拷贝数据到 ext3 文件系统格式的硬盘;而这样的操作涉及到两个不同的文件系统。“一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。

  而虚拟文件系统正是实现上述两点 Linux 特性的关键所在。虚拟文件系统(Virtual File System, 简称 VFS), 是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个 抽象功能,允许不同的文件系统共存。系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。

VFS

VFS2

  打开一个文件首先是打开文件描述符,每个对应创建一个file结构体,f_op指向一组函数open,close,read,write...(是驱动层的操作,和应用层的不是一回事),这组函数对应具体的硬件操作,f_dentry指向磁盘文件,对应一组文件系统驱动。文件系统驱动和驱动层等这些都属于内核,上图的众多结构体相关联组成虚拟文件系统VFS。两个进程打开同一个文件,后写的覆盖前写的。若两个描述符指向同一个结构体,追加型。

dup/dup2

#include<unistd.h>

int dup(int oldfd)

int dup2(int oldfd,int newfd);

dup和dup2都可用来复制现存的文件描述符,使两个文件描述符指向同一个file结构体。如果两个文件描述符指向同一个file结构体,file status flag和读写位置只保存一份在file结构体中,并且file结构体的引用计数会变为2。

示例:

原文地址:https://www.cnblogs.com/rainbow1122/p/7809262.html