文件系统

目录与文件

获取文件属性

  • stat 通过文件路径获取属性
  • fstat 通过文件描述符获取属性
  • lstat 面对符号链接文件时,获取的是符号链接文件的属性,而stat获取的是所指目标文件的属性
  • int stat(const char *pathname, struct stat *statbuf);
    - int fstat(int fd, struct stat *statbuf);
    - int lstat(const char *pathname, struct stat *statbuf);
struct stat {
               dev_t     st_dev;         /* ID of device containing file */
               ino_t     st_ino;         /* Inode number */
               mode_t    st_mode;        /* File type and mode 权限 */
               nlink_t   st_nlink;       /* Number of hard links */
               uid_t     st_uid;         /* User ID of owner */
               off_t     st_size;        /* Total size, in bytes */
               blksize_t st_blksize;     /* Block size for filesystem I/O 一块扇区的大小*/
               blkcnt_t  st_blocks;      /* Number of 512B blocks allocated  所占扇区的个数*/
...
}

文件所占磁盘大小= st_blksize * st_blocks (不等于st_size)

static off_t flen(const char *fname){
    struct stat statres;
    if (stat(fname,&statres) < 0) {
        perror("tata()");
        exit(1);
    }
    return statres.st_size;
}

int main(int argc,char **argv)
{
    if (argc < 2) {
        fprintf(stderr,"Usage...\n");
        exit(1);
    }

    long len = flen(argv[1]);
    printf("st_size = %ld\n",len);

    exit(0);
}

空洞文件

5G大小

int main(int argc,char **argv)
{
    if (argc < 2) {
        fprintf(stderr,"Usage...\n");
        exit(1);
    }
    int fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0600);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
    long err = lseek(fd,5LL*1024LL*1024LL*1024LL-1LL,SEEK_SET);
    if (err == -1) {
        perror("lseek");
        exit(1);
    }
    write(fd,"",1);
    return 0;
}

文件属性

7种文件类型 `

  • b 块设备文件
  • c 字符设备文件
  • d 目录
  • - 常规文件
  • l 符号链接文件
  • s socket文件(网络套接字文件)
  • p 匿名管道文件(不可见)

宏:S_ISREG、S_ISDIR、S_ISSOCK…

static int ftype(const char* fname) {
    if (stat(fname,&statres) < 0) {
        perror("rstat()");
        exit(1);
    }
    if (S_ISREG(statres.st_mode)) {
        return '-';
    }else if (S_ISDIR(statres.st_mode)) {
        return 'd';
    }else{
        return '?';
    }

文件访问权限

  • st_mode
    16位位图,用于表示文件类型、文件访问权限、特殊权限位
    _ _ _ (7种文件类型) _ t(粘住位) _ g+s _ u+s _ _ _ user _ _ _ group _ _ _ other共15位

  • umask:防止产生权限过松的文件

文件权限的更改与管理

  • int chmod(const char *pathname, mode_t mode);
  • int fchmod(int fd, mode_t mode); 修改一个已经成功打开的文件
  • chmod (命令)
    • chmod a+x ??x ??x ??x
    • chmod u+x ??x ??? ???
    • chmod g+x ??? ??x ???
    • chmod o+x ??? ??? ??x

文件系统

(文件或数据的存储格式)FAT、UFS
FAT
(实质)静态单链表
UFS
…|磁盘分区|…
/ \
…|柱面组|…
/ \
| 描述性信息 | inode位图 | 数据块位图 | inode | 数据块 |

inode 结构体包括:stat、亚数据信息、隐藏内容、数据库指针
数据块指针:直接数据块指针、1级、2级、3级间接数据块指针
缺陷:不善于管理小文件、大量小文件时inode满了,数据块可能大量空白

硬链接 符号连接

  • 目录文件:文件名保存在目录文件中
    | 目录项 | 目录项 | 目录项 |…
    /inode 、filename…\

  • int link(const char *oldpath, const char *newpath);
    创建硬链接 其实就是在目录文件中创建个目录项
    限制:与源文件名不同,inode相同。不能给分区建立硬链接、不能给目录建立硬链接

  • 符号链接:相当于windows下的快捷方式,block=0
    优点:可以跨分区、可以给目录建立

  • int unlink(const char *pathname);
    删除一个文件的硬连接 但并不是删除文件
    只有当一个文件的硬链接数为0 且没有进程占用该文件时一个文件才有被删除的可能(数据可被随意改写)

分析目录/读取目录内容

  • int glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob);
  • void globfree(glob_t *pglob);
  • glob 解析模式/通配符
    errfunc 保存当前出错路径和原因
    errno GLOB_NOSPACE 、GLOB_ABORTED、GLOB_NOMATCH
typedef struct {
               size_t   gl_pathc;    /* Count of paths matched so far 数量  */
               char   **gl_pathv;    /* List of matched pathnames. 路径名,类似与main argv 字符指针数组的首地址 */
               size_t   gl_offs;     /* Slots to reserve in gl_pathv.  */
} glob_t;

glob解析路径

static void Glob(){
    glob_t globres;
    int err = glob(PAT,0,&errfunc,&globres);
    if (err) {
        printf("Error code = %d\n",err);
    }

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

其他目录操作函数

  • opendir()
  • closedir()
  • readdir()
  • seekdir()
  • telldir()

解析路径

static void PathParse(char *Path) {
    DIR *dp;
    struct dirent *cur;

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

    while((cur = readdir(dp)) != NULL) {
        fprintf(stdout,"%s ",cur->d_name);
        fprintf(stdout,"type:%d ",cur->d_type);
    }

    closedir(dp);
}

时间戳

  • time()
    time_t time(time_t *tloc); 从kernel中取出时间戳(以秒为单位)

  • localtime()
    struct tm *localtime(const time_t *timep); 将时间戳转换为struct_tm 本地时间

struct tm {
               int tm_sec;    /* Seconds (0-60) */
               int tm_min;    /* Minutes (0-59) */
               int tm_hour;   /* Hours (0-23) */
...
 };
  • mktime()
    time_t mktime(struct tm *tm); 指定一块缓冲区,将 struct_tm结构体转换为时间戳,还可以检查是否溢出

  • strftime()
    size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);格式化时间字符串

time_t stamp;
time(&stamp);
//stamp = time(NULL);

struct tm *tm;
tm = localtime(&stamp);

strftime(buf,BUFSIZE,"%Y-%m-%d",tm);
puts(buf);

实现每秒钟打印一行时间戳

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

#define BUFSIZE 1024

int main()
{

    char fmttime[BUFSIZ];
    char buf[BUFSIZE];
    char res[BUFSIZE];
    int count = 0;
    FILE *fptr;

   fptr = fopen("./log","a+");
    if (fptr == NULL) {
        perror("fopen()");
        exit(1);
    }

    while(fgets(buf, BUFSIZE, fptr) != NULL) {
        count++;
    }

    while (1){
        time_t stamp;
        stamp = time(NULL);
        struct tm *struct_tm;
        struct_tm = localtime(&stamp);

        strftime(fmttime,BUFSIZE,"%Y-%m-%d %H:%M:%S",struct_tm);
        fprintf(fptr,"%d %s\n",++count,fmttime);
        fflush(fptr);
        sleep(1);
    }

    fclose(fptr);

    exit(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值