LinuxC—文件系统学习笔记

文件系统

1 目录和文件

1.1 获取文件属性信息stat

相关函数

  • stat() 得到file指向的文件并将其属性回填到buf中,面对符号链接文件时获取的是所指向的目标文件的属性

    /* Get file attributes for FILE and put them in BUF.  */
    extern int stat (const char *__restrict __file,
           struct stat *__restrict __buf) 
    
  • fstat() 得到fd指向的文件并将其属性回填到buf中

    /* Get file attributes for the file, device, pipe, or socket
       that file descriptor FD is open on and put them in BUF.  */
    extern int fstat (int __fd, struct stat *__buf)
    
  • lstat() 得到file指向的文件并将其属性回填到buf中,面对符号链接文件时获取的符号链接文件的属性

    /* Get file attributes about FILE and put them in BUF.
       If FILE is a symbolic link, do not follow it.  */
    extern int lstat (const char *__restrict __file,
            struct stat *__restrict __buf)
    

stat结构体

struct stat {
   
    dev_t     st_dev;         /* ID of device containing file 包含当前文件的设备ID号*/
    ino_t     st_ino;         /* Inode number Inode号*/
    mode_t    st_mode;        /* File type and mode 文件的权限信息*/
    nlink_t   st_nlink;       /* Number of hard links 硬链接数*/
    uid_t     st_uid;         /* User ID of owner userID*/
    gid_t     st_gid;         /* Group ID of owner groupID*/
    dev_t     st_rdev;        /* Device ID (if special file) 设备ID*/
    off_t     st_size;        /* Total size, in bytes 文件大小*/
    blksize_t st_blksize;     /* Block size for filesystem I/O 一个block有多大*/
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated 当前文件占了多少个block*/

    /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access 最后一次读的时间*/
    struct timespec st_mtim;  /* Time of last modification 最后一次改的时间*/
    struct timespec st_ctim;  /* Time of last status change 最后一次修改亚数据的时间*/

    #define st_atime st_atim.tv_sec      /* Backward compatibility */
    #define st_mtime st_mtim.tv_sec
    #define st_ctime st_ctim.tv_sec
};
  • st_mode,是一个16位的位图,用于表示文件类型,文件访问权限,及特殊权限位
  • 文件类型共有7中dcb-lsp,可以用如下7个宏定义的函数来进行判断
Because tests of the above form are common, additional macros are defined by POSIX to allow the test of the file type in st_mode to be written more concisely:

           S_ISREG(m)  is it a regular file? 常规文件

           S_ISDIR(m)  directory? 目录

           S_ISCHR(m)  character device? 字符设备

           S_ISBLK(m)  block device? 块设备

           S_ISFIFO(m) FIFO (named pipe)? 命名管道

           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.) 符号链接

           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.) 套接字

umask

umask = 0002; 0666&0002

作用:防止产生权限过松的文件

1.2 文件权限的更改/管理

  • chmod() 更改file文件的权限

    /* Set file access permissions for FILE to MODE.
       If FILE is a symbolic link, this affects its target instead.  */
    extern int chmod (const char *__file, __mode_t __mode)
    
  • fchmod() 更改一个成功打开的文件fd的权限

    /* Set file access permissions of the file FD is open on to MODE.  */
    extern int fchmod (int __fd, __mode_t __mode) __THROW
    

1.3 文件系统

文件系统的作用:文件或数据的存储和管理

1.3.1 FAT文件系统

本质就是一个静态存储的单链表,所以FAT文件系统承载的文件的大小是有上限的,N值有限,如图将一块磁盘分为N个char[SIZE]大小的数据块,用于存储数据,next用于存储指针信息,比如下图中有一个File需要用到三个数据块,且分配的数据块是1,3,7,这是在next数组中,File指向next[1],next[1]指向next[3],next[3]指向next[7],通过访问next数据就能直到File使用了那几个数据块从而访问到File的数据

在这里插入图片描述

1.3.2 UFS文件系统

在这里插入图片描述

1.4 硬链接和符号链接

硬链接

  • shell命令

    ln source source1
    
  • 作用:

    硬链接产生的source1可以认为就是给源文件起了一个别名,也就是说,两个文件名指向同一个inode,也就是同一个文件,对硬链接source1进行的操作打开source也能看见;用stat命令查看source1的属性值时可以发现source1是普通文件,同时links硬链接数增加,对于一个文件,其硬链接

符号链接

  • shell命令

    ln -s source source1
    
  • 符号链接

    符号链接产生的source1是一个新文件,通过stat查看source1属性可以看到source1是一个符号链接文件,这个文件本身不存储source的内容信息,这个文件指向source文件,通过打开source1文件,可以访问到source文件,可以理解为win下的快捷方式。

相关函数

  • link() 系统调用,给一个文件起一个新的文件名,对应shell的ln命令

    /* Make a link to FROM named TO.  */
    extern int link (const char *__from, const char *__to)
    
  • unlink() 系统调用,删除硬链接,至于这个文件是否被删除,需要看两个方面:1,硬链接数为0了;2没有任何文件描述符指向这个文件,不能删除空目录

    /* Remove the link NAME.  */
    extern int unlink (const char *__name)
    

    通过unlink(),可以构造临时文件,比如先调用tmpnam()创建一个临时文件名,然后open(),之后立马调用unlink()即可创建一个临时文件

  • remove() 删除一个一个文件或目录,不能删除空目录,对应shell的rm命令

    /* Remove file FILENAME.  */
    extern int remove (const char *__filename)
    
  • rename() 系统调用,移动文件或修改文件名,即shell中的mv命令

    /* Rename file OLD to NEW.  */
    extern int rename (const char *__old, const char *__new)
    

1.5 目录的创建和销毁/更改工作路径

  • mkidr() 系统调用,创建一个path目录并且指定权限,对应shell中的mkdir命令
/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (const char *__path, __mode_t __mode)
  • rmdir() 系统调用,删除一个空目录,对应shell中的rmdir命令
/* Remove the directory PATH.  */
extern int rmdir (const char *__path)
  • chdir() 系统调用,更改当前进程的工作路径到path,对应shell中的cd命令
/* Change the process's working directory to PATH.  */
extern int chdir (const char *__path)
    
/* Change the process's working directory to the one FD is open on.  */
extern int fchdir (int __fd)
  • getcwd() 系统调用,获取当前进程的工作路径
/* Get the pathname of the current working directory,
   and put it in SIZE bytes of BUF.  Returns NULL if the
   directory couldn't be determined or SIZE was too small.
   If successful, returns BUF.  In GNU, if BUF is NULL,
   an array is allocated with `malloc'; the array is SIZE
   bytes long, unless SIZE == 0, in which case it is as
   big as necessary.  */
extern char *getcwd (char *__buf, size_t __size)

1.6 分析目录/读取目录内容

1.6.1 glob()函数

作用,分析一个pattern,flags表示特殊要求

/* Do glob searching for PATTERN, placing results in PGLOB.
   The bits defined above may be set in FLAGS.
   If a directory cannot be opened or read and ERRFUNC is not nil,
   it is called with the pathname that caused the error, and the
   `errno' value from the failing call; if it returns non-zero
   `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
   Otherwise, `glob' returns zero.  */
#if !defined __USE_FILE_OFFSET64
extern int glob (const char *__restrict __pattern, int __flags,
		 int (*__errfunc) (const char * epath, int eerrno),
		 glob_t *__restrict __pglob) __THROW;

/* Free storage allocated in PGLOB by a previous `glob' call.  */
extern void globfree (glob_t *__pglob) __THROW;
#else
  • flags如下:
/* Bits set in the FLAGS argument to `glob'.  */
#define	GLOB_ERR	(1 << 0)/* Return on read errors.  */
#define	GLOB_MARK	(1 << 1)/* Append a slash to each name.  */
#define	GLOB_NOSORT	(1 << 2)/* Don't sort the names.  */
#define	GLOB_DOOFFS	(1 << 3)/* Insert PGLOB->gl_offs NULLs.  */
#define	GLOB_NOCHECK	(1 << 4)/* If nothing matches, return the pattern.  */
#define	GLOB_APPEND	(1 << 5)/* Append to results of a previous call.  */
#define	GLOB_NOESCAPE	(1 << 6)/* Backslashes don't quote metacharacters.  */
#define	GLOB_PERIOD	(1 << 7)/* Leading `.' can be matched by metachars.  */

#if !defined __USE_POSIX2 || defined __USE_MISC
# define GLOB_MAGCHAR	 (1 << 8)/* Set in gl_flags if any metachars seen.  */
# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */
# define GLOB_BRACE	 (1 << 10)/* Expand "{a,b}" to "a" "b".  */
# define GLOB_NOMAGIC	 (1 << 11)/* If no magic chars, return the pattern.  */
# define GLOB_TILDE	 (1 << 12)/* Expand ~user and ~ to home directories. */
# define GLOB_ONLYDIR	 (1 << 13)/* Match only directories.  */
# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error
				      if the user name is not available.  */
# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
			 GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
			 GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
#else
# define __GLOB_FLAGS	(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
			 GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
			 GLOB_PERIOD)
#endif
  • errfunc 函数指针,当解析出错的时候通过这个函数来处理出错路径和errno
  • 解析出错时还可以通过查当前函数的返回值来判断出了什么错
/* Error returns from `glob'.  */
#define    GLOB_NOSPACE   1  /* Ran out of memory.  */
#define    GLOB_ABORTED   2  /* Read error.  */
#define    GLOB_NOMATCH   3  /* No matches found.  */
#define GLOB_NOSYS 4  /* Not implemented.  */

globfree()

/* Free storage allocated in PGLOB by a previous `glob' call.  */
extern void globfree (glob_t *__pglob)

glob_t结构体

typedef struct {
   
    size_t   gl_pathc;    /* Count of paths matched so far  */
    char   **gl_pathv;    /* List of matched pathnames.  */
    size_t   gl_offs;     /* Slots to reserve in gl_pathv.  */
} glob_t;

示例

static int errFunc(const char * errPath, int errno) {
   
    puts(errPath);
    fprintf(stderr, "ERROR MSG:%s\n", strerror(errno));
    return 0;
}

int main(int argc, char **argv) {
   

    const char *pat = "/etc/*";//匹配etc目录下的所有文件
    glob_t globres;
    int err, i;

    err = glob(pat, 0, errFunc, &globres);

    if (err) {
   
        printf("Error code = %d\n", err);
        exit(1);
    }

    for (i = 0; i < globres.gl_pathc; i++) {
   
        puts(globres.gl_pathv[i]);
    }

    globfree(&globres);

    exit(0);
}
1.6.2 目录函数

在linux中目录也是一个文件,当我们使用vim打开一个目录的时候就能够看到一个目录文件中的内容,目录流就是这个目录文件的流

opendir(3) 打开一个目录流,成功返回目录流,失败返回NULL并设置errno值

DIR *opendir(const char *name);
DIR *fdopendir(int fd);

closedir(3) 关闭一个目录流

/* Close the directory stream DIRP.
   Return 0 if successful, -1 if not.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int closedir (DIR *__dirp)

readdir(3) 该函数读取打开目录流中的一行内容并返回

  • 相关定义
/* Read a directory entry from DIRP.  Return a pointer to a `struct
   dirent' describing the entry, or NULL for EOF or error.  The
   storage returned may be overwritten by a later readdir call on the
   same DIR stream.

   If the Large File Support API is selected we have to use the
   appropriate interface.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
#ifndef __USE_FILE_OFFSET64
extern struct dirent *readdir (DIR *__dirp)
    
    
/* Reentrant version of `readdir'.  Return in RESULT a pointer to the
next entry.

This function is a possible cancellation point and therefore not
marked with __THROW.  */
extern int readdir_r (DIR *__restrict __dirp,
		      struct dirent *__restrict __entry,
		      struct dirent **__restrict __result)
struct dirent {
   
    ino_t          d_ino;       /* Inode number */
    off_t          d_off;       /* Not an offset; see below 距离下一个dirent的长度*/
    unsigned short d_reclen;    /* Length of this record */
    unsigned char  d_type;      /* Type of file; not supported
                                              by all filesystem types */
    char           d_name[256]; /* Null-terminated filename */
};
  • 示例
int main(int argc, char **argv) {
   

    const char *pat = "/etc";
    DIR * dir;
    struct dirent *dt;
    int cnt = 0;

    dir = opendir(pat);

    if (dir == NULL) {
   
        perror("opendir()");
        exit(1);
    }

    while ((dt = readdir(dir)) != NULL) {
   
        puts(dt->d_name);
        cnt++;
    }

    printf("%s目录下有%d个文件\n"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值