UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)

stat函数可获得文件的属性:
UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)_第1张图片
stat函数使用pathname参数返回与此命名文件有关的信息结构。fstat函数使用fd打开文件的有关信息。lstat与stat类似,但它作用于链接时,返回该符号链接的有关信息,而不是由该符号链接引用的文件的信息。

fstatat函数为一个相对于fd的路径名返回文件统计信息,它的flag参数指示是否跟随符号链接,其值为AT_SYMLINK_NOFOLLOW被设置时,返回符号链接本身信息,否则,默认情况下,返回符号链接所指的实际文件的信息。如果fd参数为AT_FDCWD,且pathname是相对路径名,fstatat会计算相对于当前目录的pathname参数,如果pathname是一个绝对路径,fd参数会被忽略。

这四个函数的参数buf都是一个指针,它指向一个我们必须提供的结构,函数来填充这个结构,这个结构的定义可能随具体实现不同,但基本形式是:
在这里插入图片描述
UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)_第2张图片
stat结构中大多为基本系统数据类型。POSIX.1未要求st_rdev、st_blksize、st_blocks字段,SUS XSI扩展定义了这些字段。

timespec结构类型按照秒和纳秒定义时间,至少包括以下字段,其中tc_sec以秒表示,tv_nsec以纳秒表示:
在这里插入图片描述
在2008版以前的标准中,时间字段定义为st_atime、st_mtime、st_ctime,它们都是time_t类型(以秒表示),timespec结构提供了精度更高的时间戳,为保护兼容性,旧名字可定义为tv_sec成员,如st_atime可定义为st_atime.tv_set。

ls -l使用了stat函数,可获得文件的所有信息。

UNIX文件类型:
1.普通文件:最常用的文件类型,可包含文本或二进制数据,这对UNIX内核并无区别,对其解释由处理该文件的应用程序进行。但二进制可执行文件为了执行它,内核必须理解其格式,所有二进制可执行文件都遵循一种标准化格式,使得内核能确定程序文本和数据的加载位置。
2.目录文件:其包含着其他的文件名以及指向与这些文件有关信息的指针,对目录文件有读权限的进程可读该目录的内容,但只有内核可以直接写目录文件,进程必须使用某些进程更改目录。
3.块特殊文件:提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行。但FreeBSD不再支持块特殊文件,对设备的访问要通过字符特殊文件进行。
4.字符特殊文件:提供对设备的不带缓冲的访问,每次访问长度可变。系统中设备要么是字符特殊文件,要么是块特殊文件。
5.FIFO:此类文件用于进程间通信,有时也称其为命名管道。
6.套接字:此类文件用于进程间网络通信,也可用于一台宿主机上进程之间的非网络通信。(宿主机:一般指双宿主主机,指具有两个网络适配器的主机系统,并且主机系统中的寻径功能被禁止,而对外部网络的服务和访问则由网关上的代理服务器提供。它是一种结构非常简单,但安全性很高的防火墙系统,是对双宿主主机防火墙的一个改进。)
7.符号链接:此类文件指向另一个文件。

文件类型信息保存在stat结构的st_mode成员中可用以下宏确定文件类型,这些宏的参数都是stat结构的st_mode成员:
UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)_第3张图片
POSIX.1允许实现将进程间通信(Inter-Process Communication,IPC)对象(如消息队列、信号量)说明为文件,以下宏可以用来从stat结构中确定IPC对象类型,它们的参数为指向stat结构的指针:
UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)_第4张图片
读取命令行参数,对每一个参数打印其文件类型:

#include 
#include 
#include 
using namespace std;

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

    for (i = 1; i < argc; ++i) {
        cout << argv[i] << endl;
        if (lstat(argv[i], &buf) < 0) {    //使用lstat代替stat以检测符号链接
            cout << "lstat error" << endl;
            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 **";
        } 
       
        cout << ptr << endl;
    }
    exit(0);
}

运行它:
UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)_第5张图片
如上图,我们命令第一行用了反斜杠\表示要在shell的下一行继续键入命令,shell在写一行用辅助提示符>提示我们。

早期UNIX版本不提供S_ISxxx宏,需要将st_mode与屏蔽字S_IFMT相与,然后与常量S_IFxxx比较。大多系统在头文件sys/stat.h中定义了此屏蔽字和相关常量。S_ISDIR定义为:

#difine S_ISDIR (mode) (((mode) & S_IFMT) == S_IFDIR)

某单用户工作站Linux系统中各种文件类型的统计值和比例:
UNIX环境高级编程 学习笔记 第四章 文件和目录(部分)_第6张图片

你可能感兴趣的:(UNIX环境高级编程(第三版))