• Unix基本系统数据类型和stat结构体


    Unix基本系统数据类型

    历史上,某些UNIX变量已与某些C数据类型联系在一起,例如,历史上主、次设备号存放在一个1 6位的短整型中, 8位表示主设备号,另外8位表示次设备号。但是,很多较大的系统需要用多于256个值来表示其设备号,于是,就需要有一种不同的技术。(确实, SVR4用32位表示设备号:14位用于主设备号,18位用于次设备号。) 头文件<sys/types.h >中定义了某些与实现有关的数据类型,它们被称之为基本系统数据类型(primitive system data type)。有很多这种数据类型定义在其他头文件中。在头文件中这些数据类型都是用C的typedef设施来定义的。它们绝大多数都以_t 结尾。用这种方式定义了这些数据类型后,在编译时就不再需要考虑随系统不同而变的实施细节

    caddr_t 内存地址( 1 2 . 9节)
    clock_t 时钟滴答计数器(进程时间)
    comp_t 压缩的时钟滴答
    dev_t 设备号(主和次)
    fdse_t 文件描述符集
    fpos_t 文件位置
    gid_t 数值组ID
    ino_t i节点编号
    mode_t 文件类型,文件创建方式
    nlink_t 目录项的连接计数
    off_t 文件长度和位移量(带符号的)(lseek)
    pid_t 进程I D和进程组I D(带符号的)
    ptrdiff_t 两个指针相减的结果(带符号的)
    rlim_t 资源限制
    sigatomic_t 能原子地存取的数据类型
    sigset_t 信号集
    size_t 对象(例如字符串)长度(不带符号的)
    ssize_t 返回字节计数的函数(带符号的)(read, write)
    time_t 日历时间的秒计数器
    uid_t 数值用户ID
    wchar_t 能表示所有不同的字符码

    用这种方式定义了这些数据类型后,在编译时就不再需要考虑随系统不同而变的实施细节,在本书中涉及到这些数据类型的地方,我们会说明为什么使用它们。

    struct stat结构体

     stat,lstat,fstat1 函数都是获取文件(普通文件,目录,管道,socket,字符,块()的属性。函数原型#include <sys/stat.h>

    int stat(const char *restrict pathname, struct stat *restrict buf);提供文件名字,获取文件对应属性。

    int fstat(int filedes, struct stat *buf);通过文件描述符获取文件对应的属性。

    int lstat(const char *restrict pathname, struct stat *restrict buf);连接文件描述命,获取文件属性。2 文件对应的属性

    struct stat {

    mode_t st_mode; //文件对应的模式,文件,目录等

    ino_t st_ino; //inode节点号

    dev_t st_dev; //设备号码

    dev_t st_rdev; //特殊设备号码

    nlink_t st_nlink; //文件的连接数

    uid_t st_uid; //文件所有者

    gid_t st_gid; //文件所有者对应的组

    off_t st_size; //普通文件,对应的文件字节数

    time_t st_atime; //文件最后被访问的时间

    time_t st_mtime; //文件内容最后被修改的时间

    time_t st_ctime; //文件状态改变时间

    blksize_t st_blksize; //文件内容对应的块大小

    blkcnt_t st_blocks; //伟建内容对应的块数量

    };

    ----------------------------------------------------------------------------------------

    #include <unsitd.h>

    #inlcude <sys/stat.h>

    #include <sys/types.h>

    int fstat(int filedes,struct stat *buf);

    int stat(const char *path,struct stat *buf);

    int lstat(const char *path,struct stat *buf);

    这三个系统调用都可以返回指定文件的状态信息,这些信息被写到结构struct stat的缓冲区中。通过分析这个结构可以获得指定文件的信息。

    void report(struct stat *ptr)

    {

    printf("The major device no is:%d ",major(ptr->st_dev));//主设备号

    printf("The minor device no is:%d ",minor(ptr->st_dev));//从设备号

    printf("The file's node number is:%d ",ptr->st_ino);//文件节点号

    printf("The file's access mode is:%d ",ptr->st_mode);//文件的访问模式

    printf("The file's hard link number is:%d ",ptr->st_nlink);//文件的硬链接数目

    printf("The file's user id is:%d ",ptr->uid);//文件拥有者的ID

    printf("The file's group id is:%d ",ptr->gid);//文件的组ID

    printf("The file's size is:%d ",ptr->st_size);//文件的大小

    printf("The block size is:%d ",ptr->blksize);//文件占用的块数量

    printf("The number of allocated blocks is:%d ",ptr->st_blocks);//文件分配块数量

    struct tm*accesstime,*lmodifytime,*lchangetime;//访问时间,修改时间,最后一个改变时间(属性)

    accesstime=localtime(&(ptr->st_atime));

    accesstime=localtime(&(ptr->st_mtime));

    accesstime=localtime(&(ptr->st_ctime));

    printf("The last access time is: %d::%d::%d ",accesstime->hour,accesstime->min,accesstime->sec);

    printf("The last modify time is:%d::%d::%d ",lmodifytime->hour,lmodifytime->min,lmodifytime->sec);

    printf("The last change time is:%d::%d::%d ",lchangetime->hour,lchangetime->min,lchangetime->sec);

    }

    结构time_t可用用localtime转换成tm结构,获得本地时间。

     

    使用stat结构体的三个系统调用(stat, fstat, lstat)

    stat系统调用系列包括了fstat、stat和lstat,它们都是用来返回“相关文件状态信息”的,三者的不同之处在于设定源文件的方式不同。

    1

    首先隆重介绍的是一个非常重要的”VIP”人物,他是fstat, stat和lstat三者都要用到的一个结构体类型,名字叫做struct stat。可以说,没有这个struct stat的支持,上述三个系统调用将寸步难行。

     

    这个struct stat结构体在不同的UNIX/Linux系统中的定义是有小的区别的,但你完全不用担心,这并不会影响我们的使用。

    在struct stat结构体中我们常用的且各个平台都一定有的域是:

    st_mode 文件权限和文件类型信息 (记住这个黑体橘红色)

    st_ino 与该文件关联的inode

    st_dev 保存文件的设备

    st_uid 文件属主的UID号

    st_gid 文件属主的GID号

    st_atime 文件上一次被访问的时间

    st_ctime 文件的权限、属主、组或内容上一次被修改的时间

    st_mtime 文件的内容上一次被修改的时间。(和st_ctime的不同之处显而易见)

    st_nlink 该文件上硬连接的个数

    我分别提取了solaris(UNIX)和fedora(Linux)的struct stat结构体的原始定义:大家可以自己比对一下便可以发现两者确实有所不同,但主要的域是完全相同的。

    solaris的struct stat定义:

    struct stat { dev_t st_dev; ino_t st_ino; mode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; off_t st_size; timestruc_t st_atim; timestruc_t st_mtim; timestruc_t st_ctim; blksize_t st_blksize; blkcnt_t st_blocks; char st_fstype[_ST_FSTYPSZ]; };

    fedora的struct stat定义:

    struct stat { __dev_t st_dev; unsigned short int __pad1; __ino_t st_ino; __mode_t st_mode; __nlink_t st_nlink; __uid_t st_uid; __gid_t st_gid; __dev_t st_rdev; unsigned short int __pad2; __off_t st_size; __blksize_t st_blksize; __blkcnt_t st_blocks; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; unsigned long int __unused4; unsigned long int __unused5; };

    2

    大家一定注意到了,在上面列举域的时候,我在st_mode处使用了黑体橘红色标识,原因在于这个域不像其他域那么容易使用,其他的域的值显而易见,而 st_mode域是需要一些宏予以配合才能使用的。其实,通俗说,这些宏就是一些特定位置为1的二进制数的外号,我们使用它们和st_mode进行”&”操作,从而就可以得到某些特定的信息。

    文件类型标志包括:

    S_IFBLK:文件是一个特殊的块设备

    S_IFDIR:文件是一个目录

    S_IFCHR:文件是一个特殊的字符设备

    S_IFIFO:文件是一个FIFO设备

    S_IFREG:文件是一个普通文件(REG即使regular啦)

    S_IFLNK:文件是一个符号链接

    其他模式标志包括:

    S_ISUID:文件设置了SUID位

    S_ISGID:文件设置了SGID位

    S_ISVTX:文件设置了sticky位

    用于解释st_mode标志的掩码包括:

    S_IFMT:文件类型

    S_IRWXU:属主的读/写/执行权限,可以分成S_IXUSR, S_IRUSR, S_IWUSR

    S_IRWXG:属组的读/写/执行权限,可以分成S_IXGRP, S_IRGRP, S_IWGRP

    S_IRWXO:其他用户的读/写/执行权限,可以分为S_IXOTH, S_IROTH, S_IWOTH

    还有一些用于帮助确定文件类型的宏定义,这些和上面的宏不一样,这些是带有参数的宏,类似与函数的使用方法:

    S_ISBLK:测试是否是特殊的块设备文件

    S_ISCHR:测试是否是特殊的字符设备文件

    S_ISDIR:测试是否是目录(我估计find . -type d的源代码实现中就用到了这个宏)

    S_ISFIFO:测试是否是FIFO设备

    S_ISREG:测试是否是普通文件

    S_ISLNK:测试是否是符号链接

    S_ISSOCK:测试是否是socket

    3

    我们已经学习完了struct stat和各种st_mode相关宏,现在就可以拿它们和stat系统调用相互配合工作了!

    int fstat(int filedes, struct stat *buf);

    int stat(const char *path, struct stat *buf);

    int lstat(const char *path, struct stat *buf);

    聪明人一眼就能看出来fstat的第一个参数是和另外两个不一样的,对!fstat区别于另外两个系统调用的地方在于,fstat系统调用接受的是一个“文件描述符”,而另外两个则直接接受“文件全路径”。文件描述符是需要我们用open系统调用后才能得到的,而文件全路经直接写就可以了。

    stat和lstat的区别:当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;而stat返回的是该链接指向的文件的信息。(似乎有些晕吧,这样记,lstat比 stat多了一个l,因此它是有本事处理符号链接文件的,因此当遇到符号链接文件时,lstat当然不会放过。而 stat系统调用没有这个本事,它只能对符号链接文件睁一只眼闭一只眼,直接去处理链接所指文件喽)

  • 相关阅读:
    SLAM基础知识
    标准的机器学习问题
    LAS的数据格式
    Python中的多线程和多进程
    【go】log
    【亲密关系】3-吸引力
    【mysql】做 mariadb 的备库无法启动
    【zabbix-server】Supervising process xxxx which is not our child....exits
    【win10】添加程序自启动
    【Oralce】数据去重,限制某个字段的数据长度,替换空格符
  • 原文地址:https://www.cnblogs.com/soaringEveryday/p/3520494.html
Copyright © 2020-2023  润新知