• 文件和目录之文件类型


    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

    UNIX系统的大多数文件是普通文件或目录,但是也有另外一些文件类型。文件类型包括如下几种:

    (1)普通文件(regular file)。这是最常见的文件类型,这种文件包含了某种形式的数据。至于这种数据是文本还是二进制数据对于UNIX内核而言并无区别。对普通文件的解释由处理该文件的应用程序进行。

    一个值得注意的例外是二进制可执行文件。为了执行程序,内核必须理解其格式。所有二进制可执行文件都遵循一种格式,这种格式使内核能够确定程序文本和数据的加载位置。

    (2)目录文件(directory file)。这种文件包含了其他文件的名字以及指向这些文件有关信息的指针。对一个目录文件具有读权限的任一进程都可以读该目录的内容,但只有内核可以直接写目录文件。进程必须使用特定的函数才能更改目录。

    (3)块特殊文件(block special file)。这种文件类型提供对设备(例如磁盘)带缓冲的访问,每次访问以固定长度为单位进行。

    (4)字符特殊文件(character special file)。这种文件类型提供对设备不带缓冲的访问,每次访问长度可变。系统中的所有设备要么是字符特殊文件,要么是块特殊文件。

    (5)FIFO。这种类型文件用于进程间通信,有时也将其称为命名管道(named pipe)。

    (6)套接字(socket)。这种文件类型用于进程间的网络通信。套接字也可用于在一台宿主机上进程之间的非网络通信。

    (7)符号链接(symbolic link)。这种文件类型指向另一个文件。

    文件类型信息包含在stat结构的st_mode成员中。可以用表4-1中的宏确定文件类型。这些宏的参数都是stat结构中的st_mode成员。

    表4-1 <sys/stat.h>中的文件类型宏

    文件类型
    S_ISREG() 普通文件
    S_ISDIR() 目录文件
    S_ISCHR() 字符特殊文件
    S_ISBLK() 块特殊文件
    S_ISFIFO() 管道或FIFO
    S_ISLNK() 符号链接
    S_ISSOCK() 套接字

    POSIX.1允许实现将进程间通信(IPC)对象(例如,消息队列和信号量等)表示为文件。表4-2的宏用来确定IPC对象的类型。这些宏与表4-1中的不同,它们的参数并非st_mode而是指向stat结构的指针。

    表4-2 <sys/stat.h>中的IPC类型宏

    对象的类型
    S_TYPEISMQ() 消息队列
    S_TYPEISSEM() 信号量
    S_TYPEISSHM() 共享存储对象

    注:Linux系统并不将这些对象表示为文件。

    程序清单4-1 对每个命令行参数打印文件类型

    [root@localhost apue]# cat prog4-1.c 
    #include "apue.h"
    
    int 
    main(int argc, char *argv[])
    {
            int     i;
            struct stat buf;
            char    *ptr;
    
            for(i=0; i<argc; i++)
            {
                    printf("%s: ", argv[i]);
                    if(lstat(argv[i], &buf) < 0)
                    {
                            err_ret("lstat error");
                            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 **";
                    printf("%s
    ", ptr);
            }
            exit(0);
    }

    编译后运行该程序:

    [root@localhost apue]# ./prog4-1 /etc/passwd /etc /dev/initctl /dev/log /dev/tty /dev/fd0 /dev/cdrom
    ./prog4-1: regular
    /etc/passwd: regular
    /etc: directory
    /dev/initctl: fifo
    /dev/log: socket
    /dev/tty: character special
    /dev/fd0: block special
    /dev/cdrom: symbolic link

    我们特地使用了lstat函数而不是stat函数以便检测符号链接。如若使用了stat函数,则不会观察到符号链接。

    为了在Linux系统上编译该程序,必须定义_GUN_SOURCE,这样就能包括S_ISSOCK宏的定义。(我使用的是2.6.18内核Linux,编译上述程序时,并没有自己定义_GUN_SOURCE,编译通过且运行成功。)

    早期的UNIX系统版本并不提供S_ISxxx宏,于是就需要将st_mode与屏蔽字S_FIMT进行逻辑“与”运算,然后与名为S_IFxxx的常量相比较。大多数系统在文件<sys/stat.h>中定义了此屏蔽字和相关的常量。如若查看此文件,则可找到S_ISDIR宏定义为:

    #define S_ISDIR(mode)    (((mode) & S_IFMT) == S_IFDIR)
  • 相关阅读:
    第六周作业
    第五周作业
    2019春第四周作业软件
    2019年春季学期第三周作业
    2019年春季学期第二周作业(文件指针)
    7-2 求最大值及其下标 (20 分)
    7-1 查找整数 (10 分)
    7-1 抓老鼠啊~亏了还是赚了? (20 分)
    秋季学期学习总结
    第6周作业
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3501533.html
Copyright © 2020-2023  润新知