0:基本介绍:
在LINUX系统中,每一个文件都对应一个inode(索引结点),其是由文件系统中唯一数值编码,该数值称为inode编号。inode即是UNIX类的文件系统的物理对象,也是LINUX内核数据结构描述的概念实体,inode储存了与文件相关的元数据。相同文件系统中inode唯一,不同文件系统中不一定。
linux目录结构是树结构。
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);
STAT函数会返回指定路径的文件信息并存储在结构体STAT中
FSTAT函数会返回由文件描述符FD指向的文件信息。
lstat函数是对于符号链接,其返回的是链接本身,而非目标文件。
三个函数查询的结果都返回在stat结构体中,
调用失败返回-1.
下面介绍stat结构体。
主要注意第三个位置,其记录的是文件的用户组,所有者等的读写权限和文件类型
st_mode分类如下(只给出权限宏,文件类型宏用的少,自行查阅):以下宏是对于调用open/creat函数创造新文件时进行赋予的文件权限,而不是O_()的宏,后者是以什么方式进行操作文件,这是两个不同,要区别。操作文件的方式不能和创造文件时的权限冲突。
其他stat结构体成员如下:
如下代码例子,查看文件是啥类型:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>
int main(int argc,char* argv[]){
struct stat sb;
int ret;
if(argc<2){
std::cout<<"not enough"<<std::endl;
exit(0);
}
ret=stat(argv[1],&sb);
if(ret){
perror("stat error");
exit(0);
}
std::cout<<"file type :";
switch (sb.st_mode&S_IFMT)//与运算
{
case S_IFBLK:
std::cout<<"block device node\n";
break;
case S_IFCHR:
std::cout<<"character device node\n";
break;
case S_IFDIR:
std::cout<<"director\n";
break;
case S_IFIFO:
std::cout<<"ifio\n";
break;
default:
std::cout<<"other \n";
break;
}
return 0;
}
2.文件权限的系统调用(和黑框命令修改差不多)。
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char* path,mode_t mode);
int fchmod(int fd,mode_t mode);
上述两个函数都可以将文件权限修改为参数mode指定值,
前者是需要用到相对路径或者绝对路径,后者是由文件描述符。
mode_t是参数mode的合法值,这些常量能执行二进制或运算
调用成功返回0,失败返回-1.
int ret;
ret=chmod("/home/user/map.png",S_IRUSR|S_IWUSR);
/*将此文件权限设置为所有者可读,所有者可写*/
对于修改所有权(所属用户组那些)和文件的扩展操作不做介绍,学习黑框命令即可。
3.目录:
LINUX系统中,目录就是包含一个文件列表名,每个文件名映射一个INODE编号,每个文件称之为目录项,目录当然还可能包含其他目录,子目录。路径名由文件名及其一级或者多级父目录组成的,绝对目录是从根目录开始的,相对目录从当前所在目录开始。每个进程都有一个当前目录,一般是创建时从父进程继承而来。
3.1) 获得当前目录:
#include <unistd.h>
char* getcwd(char* buf,size_t size);
调用成功时,会将当前工作目录以绝对路径的方式拷贝到buf中,buf长为size,
并且返回一个指向buff的指针,拷贝失败返回NULL。
注意size的长度要确保能存放目录
char* t;
t=getwcd(NULL,0);//获得当前工作目录,不包含文件名
3.2)改变当前工作目录(黑框对应的操作是cd):
#include <unistd.h>
int chdir(const char* path);
int fchdir(int fd);//是目录的文件描述符,不是文件
前者是将当前工作目录更改为path指定路径,可以是相对,也可以是绝对,
后者是会将当前工作目录更换为文件描述符指向的路径,fd必须是打开的目录。
成功返回0,失败返回-1.
int fd1=open("/home/user",O_RDONLY);//user目录的文件描述符
int a=fchdir(fd1);//当前工作目录转移到user目录下
3.3)创建目录:
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char* path,mode_t mode);
调用此函数会创建PATH所指定的目录(可能是绝对路径,也可能是相对路径,其权限位为mode)并返回零。
shell命令的mkdir也是创建目录(把他当成一个文件夹)
若新目录的父目录拥有已设置的用户组ID位设置,或文件系统以BSD的组方式被挂截,新目录将继承父目录用户组从属关系,否则进程有效用户组ID将应用于新目录。
3.4)删除目录:
#include <unistd.h>
int rmdir(const char* path);
调用成功时,此函数会删除PATH指向的目录,并返回零,注意
PATH直线的目录必须为空,这与shell中的rmdir一致,且不能递归dfs删除(rm -f)
读取目录的系统调用不涉及,不如命令ls好用。
LINUX知识补充:
链接:目录中的每个名字至inode的映射被成为链接,即链接本质就是目录中一个指向inode的名字,所以没有限制inode的链接数目。
硬链接:硬连接指通过索引节点来进行连接。在 Linux 中,多个文件名 (一个文件包含一个目录项,目录项包含文件名和索引结点,索引结点指向磁盘内容)指向同一索引节点是存在的。比如:A 是 B 的硬链接(A 和 B 都是文件名,文件名不同,但inode相同),则 A 的目录项中的 inode 节点号与 B 的目录项中的 inode 节点号相同,即一个 inode 节点对应两个不同的文件名,两个文件名指向同一个文件,A 和 B 对文件系统来说是完全平等的。删除其中任何一个都不会影响另外一个的访问。文件的链接数量没有限制,链接为零的文件在文件系统中没有目录项。LINUX中,内核通过链接计数和使用计数来管理文件,后者是被打开的实例的计数,只有当某个文件的两个计数都为零,文件才会被删除(和软连接无关)。本质:允许一个文件拥有多个有效路径名。
软连接:其与硬链接都是指向文件系统中的文件。它是一种特殊的文件类型,软连接不会增加目录项。软连接可以是相对/绝对路径。软连接最大区别是,可以跨不同的文件系统,其可以指向任何位置。可以指向删除的文件(悬空符号链接),当文件删除时,软连接就是悬空的,删除软连接对文件本身无影响。
#include <unistd.h>
int link(const char* oldpath,const char* newpath);//绝对路径
创建硬链接,调用成功时,会为oldpath所指向的已存在的文件,在路径newpath下创建新的链接,并返回0,
oldpath的newpath指向相同的文件
/* 不能跨文件系统*/
int ret;
ret=link("/home/kidd/old","home/kidd/new");
调用成功,会创建新的目录项new,old,new指向相同文件。
新的目录项(文件)new会包含原来old的所有内容,这点注意
int symlink(const char* oldpath,const char* newpath);
调用成功 创建符号链接new指向oldpath表示的文件。
int unlink(const char* pathname);
删除链接,即从文件系统中删除路径名,若该文件是最后一个硬链接,
则文件被删除。若是符号链接,则只会删除链接,不影响目标文件。
注意unlink不会删除目录,可以用rmdir()