linux环境编程

目录

文件属性

这里主要通过 stat 结构的成员来了解文件属性,通过各种系统调用方法来获取或修改 stat 包含的属性

stat结构

struct stat {
   dev_t     st_dev;     /* ID of device containing file */
   ino_t     st_ino;     /* inode number */
   mode_t    st_mode;    /* protection */
   nlink_t   st_nlink;   /* number of hard links */
   uid_t     st_uid;     /* user ID of owner */
   gid_t     st_gid;     /* group ID of owner */
   dev_t     st_rdev;    /* device ID (if special file) */
   off_t     st_size;    /* total size, in bytes */
   blksize_t st_blksize; /* blocksize for file system I/O */
   blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
   time_t    st_atime;   /* time of last access */
   time_t    st_mtime;   /* time of last modification */
   time_t    st_ctime;   /* time of last status change */
};

字段属性

stat获取

stat 结构信息可以通过以下方法获取

#include <sys/stat.h>
int stat(const char *pathname, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
  • stat()返回所命名文件的相关信息
  • lstat()与stat()类似,当文件是符号链接时,那么该方法返回的事符号链接自身(stat()返回的是符号指向实际的文件)
  • fstat()返回以某个打开的文件描述符所指的文件的相关信息

stat()和lstat()需要有 pathname 父目录的执行权限;fstat()只要给提供有效的文件描述符,就可以调用成功

获取stat结构示例

#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    for (int i = 1; i < argc; ++i)
    {
        struct stat st;
        if (stat(argv[i], &st) != 0)
        {
            printf("stat failed!\n");
            continue;
        }
        printf("dev:\t%lu\n", st.st_dev);
        printf("ino:\t%lu\n", st.st_ino);
        printf("mode:\t%d\n", st.st_mode);
        printf("nlink:\t%lu\n", st.st_nlink);
        printf("uid:\t%d\n", st.st_uid);
        printf("gid:\t%d\n", st.st_gid);
        printf("rdev:\t%lu\n", st.st_rdev);
        printf("size:\t%lu\n", st.st_size);
        printf("blksize:\t%lu\n", st.st_blksize);
        printf("blocks:\t%lu\n", st.st_blocks);
        printf("atime:\t%ld\n", st.st_atime);
        printf("mtime:\t%ld\n", st.st_mtime);
        printf("ctime:\t%ld\n", st.st_ctime);
    }

    return 0;
}

设备ID和i节点号

st_dev 字段标识文件所驻留的设备
st_ino 字段包含了文件i节点号

使用上面两者,可在所有文件系统中唯一标识某个文件

如果针对的设备是i节点,那么 st_rdev 字段包含设备的主、辅ID

使用宏 major()minor() 可以提取dev_t值的主、辅ID

major、minor原型

unsigned int major(dev_t dev);
unsigned int minor(dev_t dev);

文件所有权

st_uidst_gid 字段分别标识文件所有者(用户ID)和所属组(组ID)

链接数

st_nlink 字段包含了指向文件链接数(硬链接)

文件类型及权限

st_mode 字段内含位掩码,标识文件类型和指定文件权限的双重作用

<---文件类型---><------------------ 权限 ----------------------->
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   | U | G | T | R | W | X | R | W | X | R | W | X |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

可以直接通过 (statbuf.st_mode & S_IFMT) == S_IFREG 判断文件类型,也可以通过下面测试宏来直接检查。

检查文件类型的宏

常量 测试宏 文件类型
S_IFREG S_ISREG() 普通文件
S_IFDIR S_ISDIR() 目录
S_IFCHR S_ISCHR() 字符设备
S_IFBLK S_ISBLK() 块设备
S_IFIFO S_ISFIFO() FIFO或管道
S_IFSOCK S_ISSOCK() 套接字
S_IFLNK S_ISLNK() 符号链接

文件权限

UGT 分别表示设置用户ID、设置组ID、粘贴位
rwx 分别表示读、写、执行权限,上面的9个rwx权限位分别表示所属用户、所属组、其他用户的权限

常量 其他值 权限位
S_ISUID 04000 Set-user-ID
S_ISGID 02000 Set-group-ID
S_ISVTX 01000 Sticky
S_IRUSR 04000 User-read
S_IWUSR 02000 User-write
S_IXUSR 01000 User-execute
S_IRGRP 04000 Group-read
S_IWGRP 02000 Group-write
S_IXGRP 01000 Group-execute
S_IROTH 04000 Other-read
S_IWOTH 02000 Other-write
S_IXOTH 01000 Other-execute

目录的权限说明

  • 读权限:可列出目录之下的内容
  • 写权限:可在目录内创建、删除文件
  • 可执行权限:可访问目录中的文件

文件大小

st_size 字段表示文件的字节数,对于符号链接,表示链接所指路径名的长度;对于共享内存对象,表示对象的大小。

st_blocks 字段表示分配给文件的总块数,块大小为512字节,其中包括了指针块所分配的空间

st_blksize 字段表示文件系统上文件进行I/O操作时的最优块大小;若I/O所采用的块大小小于该值,被视为低效

文件时间戳

st_atime: 上次访问时间
st_mtime: 上次修改时间
st_ctime: 上次文件状态发生改变的时间(i节点信息被修改就是状态发生改变)

文件属性修改方法

文件所有权

#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
  • chown()改变由pathname参数命名的文件的所有权
  • lchown()同上,区别pathname为符号链接时,则改变链接本身(chown改变的是链接所指文件)
  • fchown()同上,传入的参数是文件描述符

如果只是打算修改用户ID或组ID之一,只需要将另一个改为-1即可

文件权限

检查文件访问权限

#include <unistd.h>
int access(const char *pathname, int mode);

若参数pathname为符号链接,access()将对其解引用
mode是常量按位或的位掩码。满足权限则返回0, 否则返回-1

常量 描述
F_OK 文件存在
R_OK 文件可读
W_OK 文件可写
X_OK 文件可执行
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
  • chmod()更改pathname参数所指文件的权限,如果是符号链接,则修改符号链接所指向的文件权限
  • fchmod()功能同上,修改的是文件描述符所指的文件权限

文件链接数

修改文件连接数的方法有很多,比如创建新文件(create())、创建硬连接(link())、删除文件、删除硬连接(unlink)等等,都可以改变文件的链接数目,当链接数目为0的时候,就会把文件彻底删掉

mkdir(), rmdir()是对目录的创建和删除方法,同样也改变目录的链接数(目录没有硬连接)

文件时间戳

#include <sys/stat.h>
int utime(const char*pathname, const struct utimbuf *buf);
int utimes(const char*pathname, const struct timeval tv[2]);
int futimens(int fd, const struct timespec time[2]);
int lutimes(const char *pathname, const struct timeval tv[2]);
  • utime()如果buf为null,将文件上次访问时间和修改时间设置为当前时间,否则按照buf结构的相应字段去修改时间
  • utimes()可以用微秒的精度来指定时间值
  • futimes()可以使用文件描述符来修改时间(其他功能和utimes一样)
  • lutimes()与utimes()的区别就是如果文件是符号链接,lutimes()修改的是符号链接本身

参考

  • UNIX环境高级编程
  • Linux/UNIX系统编程手册(上册)

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 245292011@qq.com

文章标题:linux环境编程

字数:1.8k

本文作者:常丁方

发布时间:2020-11-30, 19:12:32

最后更新:2021-08-25, 18:31:45

原始链接:http://changdingfang.com/2020/11/30/notes/linux/linux-program/
×

喜欢就点赞,疼爱就打赏

资源