Android C++系列:Linux文件系统(二)

简介: dup和dup2都可用来复制一个现存的文件描述符,使两个文件描述符指向同一个file结 构体。如果两个文件描述符指向同一个file结构体,File Status Flag和读写位置只保存一份在file结构体中,并且file结构体的引用计数是2。如果两次open同一文件得到两个文件 描述符,则每个描述符对应一个不同的file结构体,可以有不同的File Status Flag和读写 位置。请注意区分这两种情况。

image.png


1. VFS虚拟文件系统


Linux支持各种各样的文件系统格式,如ext2、ext3、reiserfs、FAT、NTFS、iso9660 等等,不同的磁盘分区、光盘或其它存储设备都有不同的文件系统格式,然而这些文件系统 都可以mount到某个目录下,使我们看到一个统一的目录树,各种文件系统上的目录和文件 我们用ls命令看起来是一样的,读写操作用起来也都是一样的,这是怎么做到的呢?Linux 内核在各种不同的文件系统格式之上做了一个抽象层,使得文件、目录、读写访问等概念成 为抽象层的概念,因此各种文件系统看起来用起来都一样,这个抽象层称为虚拟文件系统 (VFS,Virtual Filesystem)。这一节我们介绍运行时文件系统在内核中的表示。


image.png


1.1 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。如果两次open同一文件得到两个文件 描述符,则每个描述符对应一个不同的file结构体,可以有不同的File Status Flag和读写 位置。请注意区分这两种情况。


#include <unistd.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>
int main(void) {
  int fd, save_fd;
  char msg[] = "This is a test\n";
  fd = open("somefile", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); 
  if(fd<0) {
    perror("open");
    exit(1); 
  }
  save_fd = dup(STDOUT_FILENO);
  dup2(fd, STDOUT_FILENO);
  close(fd);
  write(STDOUT_FILENO, msg, strlen(msg)); dup2(save_fd, STDOUT_FILENO);       
  write(STDOUT_FILENO, msg, strlen(msg)); close(save_fd);
  return 0; 
}


示例:


image.png


2. 常用文件操作


2.1 stat


#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>
int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
struct stat {
  dev_t  st_dev; /* ID of device containing file */
  ino_t  st_ino;/* inode number */
  mode_t  st_mode;/* protection */
  nlink_t st_nlink;/* number of hard links */
  uid_t st_uid;/* user ID of owner */
  gid_t st_gid;/* group ID of owner */
  dev_t st_rdev;/* device ID (if special file) */
  off_t st_size;/* total size, in bytes */
  blksize_t st_blksize;/* blocksize for file system I/O */
  blkcnt_t st_blocks;/* number of 512B blocks allocated */
  time_t st_atime;/* time of last access */
  time_t st_mtime;/* time of last modification */
  time_t st_ctime;/* time of last status change */


stat既有命令也有同名函数,用来获取文件Inode里主要信息,stat 跟踪符号链 接,lstat不跟踪符号链接


stat里面时间辨析


atime(最近访问时间): mtime(最近更改时间):指最近修改文件内容的时间 ctime(最 近改动时间):指最近改动Inode的时间 ## access


#include <unistd.h>
int access(const char *pathname, int mode);


按实际用户ID和实际组ID测试,跟踪符号链接 参数mode


R_OK 是否有读权限
W_OK 是否有写权限
X_OK 是否有执行权限
F_OK 测试一个文件是否存在


实际用户ID: 有效用户ID:sudo执行时,有效用户ID是root,实际用户ID是xingwen- peng


2.1 chmod


#include <sys/stat.h>
int chmod(const char *path, mode_t mode); 
int fchmod(int fd, mode_t mode);


2.2 chown


#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group); 
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);


chown使用时必须拥有root权限。


image.png


2.3 utime


2.4 truncate


#include <unistd.h> #include <sys/types.h>
int truncate(const char *path, off_t length); 
int ftruncate(int fd, off_t length);


2.4 link


2.4.1 link


创建一个硬链接


当rm删除文件时,只是删除了目录下的记录项和把inode硬链接计数减1,当硬链接计数 减为0时,才会真正的删除文件。


#include <unistd.h>
int link(const char *oldpath, const char *newpath);


  • 硬链接通常要求位于同一文件系统中,POSIX允许夸文件系统
  • 符号链接没有文件系统限制
  • 通常不允许创建目录的硬链接,某些unix系统下超级用户可以创建目录的硬链
  • 创建目录项以及增加硬链接计数应当是一个原子操作


2.4.2 symlink


int symlink(const char *oldpath, const char *newpath)


2.4.3 readlink


读符号链接所指向的文件名字,不读文件内容


ssize_t readlink(const char *path, char *buf, size_t bufsiz)


2.4.4 unlink


int unlink(const char *pathname)


  1. 如果是符号链接,删除符号链接
  2. 如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode
  3. 如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭该文件时,kernel才真正 去删除该文件
  4. 利用该特性创建临时文件,先open或creat创建一个文件,马上unlink此文件


2.5 rename


文件重命名


#include <stdio.h>
int rename(const char *oldpath, const char *newpath);


2.6 chdir


#include <unistd.h>
int chdir(const char *path); 
int fchdir(int fd);


改变当前进程的工作目录。


2.7 getcwd


获取当前进程的工作目录


#include <unistd.h>
char *getcwd(char *buf, size_t size);


2.8 pathconf


#include <unistd.h>
long fpathconf(int fd, int name); 
long pathconf(char *path, int name);


3. 目录操作


3.1 mkdir


#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);


3.2 rmdir


#include <unistd.h>
int rmdir(const char *pathname);


3.3 opendir/fdopendir


#include <sys/types.h> 
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd);


3.4 readdir


#include <dirent.h>
struct dirent *readdir(DIR *dirp);


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


3.5 rewinddir


#include <sys/types.h> 
#include <dirent.h>
void rewinddir(DIR *dirp);


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


3.6 telldir/seekdir


#include <dirent.h>
long telldir(DIR *dirp);
#include <dirent.h>
void seekdir(DIR *dirp, long offset);


3.7 closedir


#include <sys/types.h> 
#include <dirent.h>
int closedir(DIR *dirp);


3.8 递归遍历目录


递归列出目录中的文件列表


#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <dirent.h> 
#include <stdio.h> 
#include <string.h>
#define MAX_PATH 1024
/* dirwalk: apply fcn to all files in dir */ 
void dirwalk(char *dir, void (*fcn)(char *)) {
  char name[MAX_PATH]; 
  struct dirent *dp; 
  DIR *dfd;
  if ((dfd = opendir(dir)) == NULL) { 
    fprintf(stderr, "dirwalk: can't open %s\n",dir);
    return;
  }
  while ((dp = readdir(dfd)) != NULL){ 
    if (strcmp(dp->d_name, ".") == 0|| strcmp(dp->d_name, "..") == 0)
      continue; /* skip self and parent */
    if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))
      fprintf(stderr, "dirwalk: name %s %s too long\n", dir, dp->d_name);
    else {
      sprintf(name, "%s/%s", dir, dp->d_name); (*fcn)(name);
    } 
  }
  closedir(dfd); 
}
/* fsize: print the size and name of file "name" */ 
void fsize(char *name)
{
struct stat stbuf;
if (stat(name, &stbuf) == -1) {
fprintf(stderr, "fsize: can't access %s\n", name); return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, fsize);
printf("%8ld %s\n", stbuf.st_size, name);
}
int main(int argc, char **argv) {
  if (argc == 1) /* default: current directory */ 
    fsize(".");
  else
    while (--argc > 0)
      fsize(*++argv); 
  return 0;
}


然而这个程序还是不如ls -R健壮,它有可能死循环,思考一下什么情况会导致死循环。


4. 小结


本文介绍了Virtual Filesystem(VFS)虚拟文件系统及其原理,以及stat、chmod、chown、utime等常用文件操作函数以及mkdir、rmdir、readdir等目录操作函数。

目录
相关文章
|
9月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
2087 77
|
9月前
|
自然语言处理 监控 Linux
Linux 内核源码分析---proc 文件系统
`proc`文件系统是Linux内核中一个灵活而强大的工具,提供了一个与内核数据结构交互的接口。通过本文的分析,我们深入探讨了 `proc`文件系统的实现原理,包括其初始化、文件的创建与操作、动态内容生成等方面。通过对这些内容的理解,开发者可以更好地利用 `proc`文件系统来监控和调试内核,同时也为系统管理提供了便利的工具。
435 16
|
9月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
10月前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
251 16
|
11月前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
573 15
|
12月前
|
Ubuntu Unix Linux
Linux网络文件系统NFS:配置与管理指南
NFS 是 Linux 系统中常用的网络文件系统协议,通过配置和管理 NFS,可以实现跨网络的文件共享。本文详细介绍了 NFS 的安装、配置、管理和常见问题的解决方法,希望对您的工作有所帮助。通过正确配置和优化 NFS,可以显著提高文件共享的效率和安全性。
2478 7
|
12月前
|
存储 运维 监控
Linux--深入理与解linux文件系统与日志文件分析
深入理解 Linux 文件系统和日志文件分析,对于系统管理员和运维工程师来说至关重要。文件系统管理涉及到文件的组织、存储和检索,而日志文件则记录了系统和应用的运行状态,是排查故障和维护系统的重要依据。通过掌握文件系统和日志文件的管理和分析技能,可以有效提升系统的稳定性和安全性。
281 7
|
12月前
|
安全 Linux 数据安全/隐私保护
深入Linux操作系统:文件系统和权限管理
在数字世界的海洋中,操作系统是连接用户与硬件的桥梁,而Linux作为其中的佼佼者,其文件系统和权限管理则是这座桥梁上不可或缺的结构。本文将带你探索Linux的文件系统结构,理解文件权限的重要性,并通过实际案例揭示如何有效地管理和控制这些权限。我们将一起航行在Linux的命令行海洋中,解锁文件系统的奥秘,并学习如何保护你的数据免受不必要的访问。
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
303 8
|
存储 Linux 文件存储
Linux文件系统
Linux文件系统 一切皆文件 在Linux中,“一切皆文件”的概念意味着系统中的所有资源,包括硬件设备、目录及进程等,均被视为文件。这种设计简化了操作和管理,具体包括: 普通文件:存储数据的常规文件。 目录文件:包含其他文件和子目录的文件。 进程文件:在/proc目录下代表系统中运行的进程。 设备文件:位于/dev目录,代表硬件设备。 网络字节流套接字文件:用于网络通信的数据流。 链接文件:指向另一个文件的符号链接或硬链接。 管道文件:用于进程间通信的文件。
211 7

热门文章

最新文章