【问题标题】:What is `S_ISREG()`, and what does it do?什么是`S_ISREG()`,它有什么作用?
【发布时间】: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 上完美运行。

标签: c linux macos unix operating-system


【解决方案1】:

S_ISREG() 是一个宏,用于解释从系统调用 stat() 返回的 stat-struct 中的值。如果参数(struct stat 中的 st_mode 成员)是常规文件,则计算结果为 true。

请参阅man statman fstatman 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)
    

    这在我的简化版本中基本相同。

    【讨论】:

    【解决方案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,但可以很容易地使用它。

    【讨论】:

      猜你喜欢
      • 2011-01-14
      • 2019-04-26
      • 2016-04-29
      • 2012-10-04
      • 1970-01-01
      • 2017-06-20
      • 2019-12-25
      • 2010-10-02
      • 2015-02-06
      相关资源
      最近更新 更多