什么是`S_ISREG()`,它有什么作用?
Posted
技术标签:
【中文标题】什么是`S_ISREG()`,它有什么作用?【英文标题】:What is `S_ISREG()`, and what does it do? 【发布时间】:2017-03-02 23:24:45 【问题描述】:我在一个检索文件属性的 C 程序中遇到了宏 S_ISREG()
。不幸的是,网上没有关于这个宏的任何基本信息。对此有一些更高级的讨论,但它们超出了我的要求。
什么是S_ISREG()
,它有什么作用?在检索文件属性的程序的上下文中,它的用途是什么?具体是做什么的?
谢谢。
【问题讨论】:
@Clifford 谢谢。关于这个宏的唯一其他问题是关于更高级的应用程序。 @ryyker 不,不是。如果您阅读您发布的问题,您会发现它侧重于更高级的应用程序。 @ryyker 这个问题假设你已经知道S_ISREG
的用途。
您可能必须链接到“高级应用程序”我仍在努力了解有关此问题的任何讨论如何变得复杂 - 除非您只是表示讨论处理的是使用S_ISREG
只是一小部分。 stat()
手册页中的示例显示了对 st_mode
的测试 - 这些宏只是将该测试包装成布尔结果。
您无需在线即可获取文档; man 2 stat
在 linux 上完美运行。
【参考方案1】:
S_ISREG() 是一个宏,用于解释从系统调用 stat() 返回的 stat-struct 中的值。如果参数(struct stat 中的 st_mode 成员)是常规文件,则计算结果为 true。
请参阅man stat
、man fstat
或man inode
(link to inode man page) 了解更多详情。这是手册页的相关部分:
Because tests of the above form are common, additional macros are defined by POSIX to allow the test of the file type in st_mode to be written more concisely:
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.)
The preceding code snippet could thus be rewritten as:
stat(pathname, &sb);
if (S_ISREG(sb.st_mode))
/* Handle regular file */
【讨论】:
【参考方案2】:它测试使用stat()
函数检索到的stat
结构的st_mode
成员,以确定该文件是否是常规文件(即在磁盘上或大容量存储上,而不是说是目录、套接字、符号链接例如。
struct stat sb;
if( stat( file_path, &sb) != -1) // Check the return value of stat
if( S_ISREG( sb.st_mode ) != 0 )
printf( "%s is a file", file_path ) ;
else
printf( "%s is not a file", file_path ) ;
st_mode
成员包含被S_IFMT
(0170000) 屏蔽的 4 位。这些位的值是:
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
所以宏 S_ISREG 可以这样定义:
#define S_ISREG( m ) (((m) & S_IFMT) == S_IFREG)
由于它是一个宏,您可以在头文件sys/stat.h
中查看它的实际定义。在 GNU 标头中,它是这样定义的:
#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
...
#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
这在我的简化版本中基本相同。
【讨论】:
你的 if-test 是倒置的。如果 S_ISREG() 不为零,则所讨论的对象是常规文件。 sourceware.org/git/?p=glibc.git;a=blob;f=io/sys/… 和 sourceware.org/git/?p=glibc.git;a=blob;f=bits/… 对于好奇的人【参考方案3】:定义 S_ISREG 的 POSIX 标准实际上是在线的。
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html
引用:
应提供以下宏来测试文件是否属于指定类型。提供给宏的值 m 是来自 stat 结构的 st_mode 值。如果测试为真,则宏应评估为非零值;如果测试为假,则为 0。
[...]
S_ISFIFO(m)
测试管道或 FIFO 特殊文件。
S_ISREG(m)
测试常规文件。
S_ISLNK(m)
测试符号链接。
[...]
使用 S_ISREG 的典型方法是首先调用 stat
函数以使用有关文件的信息填充 struct stat
对象。那么这个结构的st_mode
成员的值,一个整数类型,就可以用这个宏来测试了。
除了标准之外,还有来自各种在线系统的手册页,以及关于使用 stat 进行编程的教程。***有一个page on stat,有一个明显完整的代码示例。虽然它没有S_ISREG
,但可以很容易地使用它。
【讨论】:
以上是关于什么是`S_ISREG()`,它有什么作用?的主要内容,如果未能解决你的问题,请参考以下文章