linux系统文件类型有七种,即:普通文件、目录文件、字符设备、块设备、管道文件、链接文件和套接字文件。
通过 man 2 stat 可获取到 其中 st_mode 可以用来判别服务的类型。原文如下:
The following POSIX macros are defined to check the file type using the st_mode field:
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
其中st_mode字段涉及到文件类型的判断如下:
The following flags are defined for the st_mode field:
S_IFMT 0170000 bit mask for the file type bit fields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
综上,即通过 macros宏命令 S_ISREG(m) 可以判断是否为普通文件, S_ISDIR(m) 判断是否为路径……
在 sys/stat.h 文件中可以找到macros的定义,如下
/* Test macros for file types. */
#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
#define S_ISCHR(mode) __S_ISTYPE((mode), __S_IFCHR)
#define S_ISBLK(mode) __S_ISTYPE((mode), __S_IFBLK)
#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
#ifdef __S_IFIFO
# define S_ISFIFO(mode) __S_ISTYPE((mode), __S_IFIFO)
#endif
#ifdef __S_IFLNK
# define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
#endif
#if defined __USE_BSD && !defined __S_IFLNK
# define S_ISLNK(mode) 0
#endif
#if (defined __USE_BSD || defined __USE_UNIX98 || defined __USE_XOPEN2K) \
&& defined __S_IFSOCK
# define S_ISSOCK(mode) __S_ISTYPE((mode), __S_IFSOCK)
#elif defined __USE_XOPEN2K
# define S_ISSOCK(mode) 0
#endif
预先定义一个 函数 __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask)),通过传入 mode 与 __S_IFMT 做 按位与 后的结果 与 mask 比较,如果与传入的mask一样,则判断为该类型文件。
首先,在 sys/stat.h 中搜索 __S_IFMT 来查找定义部分,如下文
#include <bits/stat.h>
#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN
# define S_IFMT __S_IFMT
# define S_IFDIR __S_IFDIR
# define S_IFCHR __S_IFCHR
# define S_IFBLK __S_IFBLK
# define S_IFREG __S_IFREG
# define S_IFDIR __S_IFDIR
# define S_IFCHR __S_IFCHR
# define S_IFBLK __S_IFBLK
# define S_IFREG __S_IFREG
# ifdef __S_IFIFO
# define S_IFIFO __S_IFIFO
# endif
# ifdef __S_IFLNK
# define S_IFLNK __S_IFLNK
# endif
# if (defined __USE_BSD || defined __USE_MISC || defined __USE_UNIX98) \
&& defined __S_IFSOCK
# define S_IFSOCK __S_IFSOCK
# endif
#endif
即可以在 #include <bits/stat.h>中 找到相关定义,打开bits/stat.h 文件,继续搜索__S_IFMT ,得到如下内容:
/* Encoding of the file mode. */
#define __S_IFMT 0170000 /* These bits determine file type. */
/* File types. */
#define __S_IFDIR 0040000 /* Directory. */
#define __S_IFCHR 0020000 /* Character device. */
#define __S_IFBLK 0060000 /* Block device. */
#define __S_IFREG 0100000 /* Regular file. */
#define __S_IFIFO 0010000 /* FIFO. */
#define __S_IFLNK 0120000 /* Symbolic link. */
#define __S_IFSOCK 0140000 /* Socket. */
上文先定义了 文件类型的掩码 __S_IFMT 为 0170000 八进制的。然后针对 七种文件类型定义了不同的编码。
###########
通过阅读以上各个定义,回过头重新看 宏命令的定义(只罗列了部分):
#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
#define S_ISCHR(mode) __S_ISTYPE((mode), __S_IFCHR)
1、即判别一个文件是否为目录时,可以调用S_ISDIR(mode),宏命令,其函数原型为 调用 __S_ISTYPE((mode), __S_IFDIR)
2、__S_IFDIR 的编码为 0040000 ,八进制,即 传参后 __S_ISTYPE((mode), 0040000 )
3、参考__S_ISTYPE 的原型 :#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask)),其中__S_IFMT的编码为0170000 ,八进制。
传参后如下:#define __S_ISTYPE(mode, __S_IFDIR ) (((mode) & __S_IFMT) == (__S_IFDIR ))
即 : #define __S_ISTYPE(mode, 0040000 ) (((mode) & 0170000 ) == (0040000 ))
4、mode 参数为 struct stat 中 st_mode的值, 可以通过stat() 函数获取。
struct stat mystat;
stat("/data/natpan/tmp/LTars/l_file",&mystat)
即 mystat.st_mode 为传入 __S_ISTYPE 函数中的 mode。
5、 通过 mystat.st_mode 与掩码 __S_IFMT 按位与,结果与 __S_IFDIR 比较,相同则为 目录。
6、其余文件类型 判断方法类似。
方便按位运算,打印了各个类型定义编码的 二进制格式
S_IFMT :1111000000000000 Octal: 0170000 ## bit mask for the file type bit fields
S_IFSOCK :1100000000000000 Octal: 0140000 socker
S_IFLNK :1010000000000000 Octal: 0120000 symbolic link
S_IFREG :1000000000000000 Octal: 0100000 regular file
S_IFBLK :0110000000000000 Octal: 0060000 block device
S_IFDIR :0100000000000000 Octal: 0040000 directory
S_IFCHR :0010000000000000 Octal: 0020000 character device
S_IFIFO :0001000000000000 Octal: 0010000 FIFO