文件系统与函数

 

参考目录:

Linux 内核设计与实现 第13章 虚拟文件系统

Linux 程序设计与实现 第3章  文件操作

 

内核文件系统主要数据结构:

* 超级块对象 super_block,代表一个具体的已安装文件系统

* 索引结点对象  inode,代表一个具体文件

* 文件对象 file,代表由进程打开的文件

* 目录项对象 dentry, 代表一个目录项,是路径的一个组成部分

* 超级块操作 super_operations,包括内核针对特定文件系统所能调用的方法

* 索引操作 inode_operations, 包括内核针对特定文件所能调用的方法

* 文件操作 file_operations, 包括进程针对已打开文件所能调用的方法

* 目录操作 dentry_operations, 包括内核针对特定目录所能调用的方法

 

一、文件描述符(file descriptors) 

内核通过文件描述符来识别每一个文件。 范围从 0 - OPEN_MAX-1 , 每个进程能够打开的文件数量。

UNIX Shell: <unistd.h>

  0 表示输入  STDIN_FILENO

  1 表示输出  STDOUT_FILENO

  2 表示错误 STDERR_FILENO

 

二、文件I/O操作

open, create, read, write,ioctl, close

 

1. 文件打开 open 或创建

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int open(const char *path, int oflag, ...); int openat(int fd, const char *path, int oflag, ...);
// 当成功时返回file destiptor, -1 失败

参数说明:
* 第一个const char *path 表示是要打开或创建的文件名称
* oflag参数说明此函数多个选择,参数定义在fcntl.h头文件中
O_RDONLY O_WRONLY O_RDWR

 

2. 创建文件 create

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int create(const char *pathname, mode_t moe);
成功返回文件描述符,失败返回-1

此函数等同于
int open(pathname, O_WRONLY);

 

 

3. 关闭文件 close

#include <unistd.h>
int close(int fileds);
成功返回0,出错返回-1

 

 

4. lseek函数

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int filedes, off_t offset, int whence);
成功返回新的文件位移,出错为-1

参数解释:
filedes 是文件描述符
如果 whence 是 SEEK_SET, 则将该文件位移量设置为距文件开始处offset个字节
如果 whence 是 SEEK_CUR, 则将该文件的位移量设置为其当前值加offset, offset可为正或负
如果 whence 是 SEEK_END, 则将该文件的位移量设置为文件长度加offset, offset可为正或负

 

 

5. read函数

#include <unistd.h>
ssize_t read(int filedes, void buff, size_t nbytes);
// 成功返回读到的字节数,若已到文件尾为0,若出错为-1

 

6. write 函数

#include <unistd.h>
ssize_t write(int filedes, const void *buff, size_t nbytes);
成功为已写的字节数,出错-1

 

/* 从标准输入中读取,输出到标准输出 */

#include <unistd.h> // read, write 用到的头文件 #include <stdio.h> // printf用到的头文件 #include <stdlib.h> // exit用到头文件 #define BUFFSIZE 4096 int main(void) { int n; char buf[BUFFSIZE]; while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) if (write(STDOUT_FILENO, buf, n) != n) printf("write error"); if (n < 0) printf("read error"); exit(0); }

 

 

7. dup 和 dup2 函数

#include <unistd.h>
int dup(int filedes);   // 返回新的文件描述,最小值
int dup2(int filedes, int filedes2); // filedes2参数指定新描述符的数值
成功返回新的文件描述符,出错为-1

 

 

8. fcntl 函数

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int fcntl(int fieldes, int cmd, ...);
出错返回-1

 

fnctl 函数有五种功能:

复制一个现存的描述符(cmd = F_DUPFD)

获得/设置文件描述符标记(cmd = F_GETFD 或 F_SETFD)

获得/设置文件状态标记(cmd = F_GETFL 或 F_SETFL)

获得/设置异步I/O所有权(cmd = F_GETOWN 或 F_SETOWN)

获得/设置记录锁(cmd = F_GETLK, F_SETLK 或 F_SETLKW)

 

9. ioctl 函数

#include <unistd.h>
#include <sys/ioctl.h>

int ioctl(int filedes, int request, ...);
出错返回-1,成功则为其他值

 

 

 

三、目录操作<dirent.h>

#include <sys/types.h>
#include <sys/stat.h>

int stat(const char pathname, struct stat buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char pathname, struct stat *buf);
成功返回0, 出错为-1

 

 

struct stat {

  mode_t st_mode;   // 文件类型与权限

  ino_t  st_ino;   // i-node 序列号

  dev_t st_dev;  // 驱动号

  dev_t  st_rdev // 特殊设备文件驱动号

  nlink_t st_nlink;  // 链接数量

  uid_t st_uid;  // 文件所有者ID

  gid_t st_gid  // 文件所有者组ID

  off_t  st_size;  // 文件大小

  time_t st_atime;  // 最后访问时间

  time_t st_mtime;  // 最后修改时间

  time_t st_ctime;  // 最后变更时间

  long st_blksize;   // 最优IO块大小

  long st_blocks;   // 512字节分配数

};

 

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    int            i;
    struct stat    buf;
    char        *ptr;

    for (i = 1; i < argc; i++) {
        printf("%s: ", argv[i]);
        if (lstat(argv[i], &buf) < 0) {
            printf("lstat error");
            continue;
        }
        if (S_ISREG(buf.st_mode))
            ptr = "regular";
        else if (S_ISDIR(buf.st_mode))
            ptr = "directory";
        else if (S_ISCHR(buf.st_mode))
            ptr = "character special";
        else if (S_ISBLK(buf.st_mode))
            ptr = "block special";
        else if (S_ISFIFO(buf.st_mode))
            ptr = "fifo";
        else if (S_ISLNK(buf.st_mode))
            ptr = "symbolic link";
        else if (S_ISSOCK(buf.st_mode))
            ptr = "socket";
        else
            ptr = "** unknown mode **";
        printf("%s\n", ptr);
    }
    exit(0);
}


/*
➜  filedir ./filetype /etc /dev/tty.Bluetooth-Incoming-Port /dev/sdt /var/spool /bin /dev/profile 
/etc: symbolic link
/dev/tty.Bluetooth-Incoming-Port: character special
/dev/sdt: character special
/var/spool: directory
/bin: directory
/dev/profile: character special

*/

 

 

 

 

opendir, closedir, readdir, telldir, seekdir

 

1. opendir 打开目录

/* 
* 打开目录并建立目录流
* 成功:返回DIR结构的指针
* 失败:返回NULL
*/
#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name);

 

2. readdir 读取类似于链表的目录项

/*
 * 读取目录
 * 成功:返回下一个目录项的指针
 * 错误或到达未尾:返回NULL
 */
#include <sys/types.h>
#include <dirent.h>

struct dirent * readdir(DIR *dirp);

 

 

3. telldir 返回当前位置

/*
 * 查看当前位置
 */
#include <sys/types.h>
#include <dirent.h>

long int telldir(DIR *dirp);

 

 

4. seekdir

 

5. 关闭目录 closedir

  

编程练习: 完成扫描目录程序

 

 

内核虚拟文件系统(VFS):为用户空间提供了文件和文件系统相关的接口。

 

posted @ 2017-12-19 23:29  elewei  阅读(318)  评论(0)    收藏  举报