zoukankan      html  css  js  c++  java
  • Apue.2e chapter4

    今天玩了会Lubuntu,也试了一试最新的codelite,凭良心说codelite做的比code::blocks更好用,虽然功能没有后者强大,但是手感上更类似visual studio,快捷键也相仿。

    另外code::blocks使用xterm太瞎眼,改为xfce4-terminal,方法是将Environments settings-General settings-Terminal to launch console programs中的字符串改为xfce4-terminal –T $TITLE –x

    即可,选项可以自己man后根据情况修改。

    本章继续深入文件方面的学习。

    stat,fstat和lstat

    #include <sys/stat.h>

    int stat(const char *restrict pathname, struct stat *restrict buf); //指定路径文件的信息,符号链接返回链接文件信息

    int stat(int filedes, struct stat *buf);    //指定文件描述符的相关信息

    int lstat(const char *restrict pathname, struct stat *restrict buf); //如果是符号链接,返回符号链接的相关信息

    struct stat{

        mode_t st_mode; //file type & mode (permissions)

        ino_t st_ino; //i-node number (serial number)

        dev_t st_dev; //device number (file system)

        dev_t st_rdev; //device number for special files

        nlink_t st_nlink; //number of links

        uid_t st_uid; //user ID of owner

        gid_t st_gid; //group ID of owner

        off_t st_size; //size in bytes, for regular files

        time_t st_atime; //time of last access

        time_t st_mtime; //time of last modification

        time_t st_ctime; //time of last file status change

        blksize_t st_blksize; //best I/O block size

        blkcnt_t st_blocks; //number of disk blocks allocated

    }

    红色字段为SUS扩展要求,其余为Posix.1要求。该结构被ls –l 调用。

    文件类型

    • 普通文件,包括一切文本文件和可执行文件;
    • 目录文件:注意目录只能由内核进行"写"操作;
    • 块(block)设备文件:提供对设备带缓冲的访问,每次访问以固定长度为单位进行;
    • 字符(character)设备文件:提供对设备不带缓冲的访问,每次访问的长度可变;
    • FIFO:命名管道,主要用于进程间通信;
    • socket:套接字,用于进程间网络通信;
    • 符号链接:指向另一个文件。

    文件类型信息存在于st_mode之中,可以通过相关宏来确认,包括S_ISREG(),S_ISDIR(),S_ISCHR(),S_ISBLK(),S_ISFIFO(),S_ISLNK(),S_ISSOCK(),参数都是mode_t格式;

    POSIX.1允许将IPC对象表示为文件,可以用以下宏测试:S_TYPEISMQ()(消息队列),S_TYPEISSEM()(信号量),S_TYPEISSHM()(共享存储对象)。注意这一点在很多实现中被忽略掉了。

    在Linux上,必须#define _GNU_SOURCE才能使用S_ISSOCKET这个宏!

    早期UNIX不提供这些宏,需要自行编写。

    UID和GID

    这段主要强调了一种特殊情况:需要将文件的有效用户ID设为文件所有者ID时。

    SUID特殊权限:仅对可执行文件有效,属于x的加强版,应付上述特殊情况。

    SGID特殊权限:可以对目录有效,其他类似SUID。

    SVTX特殊权限:和上面两个没啥关系,也是特殊权限的一种。仅对目录有效,当用户在有t权限的目录下建立档案或目录时,仅有自己和root有删除权限。

    分清楚有效ID和所有者ID,前者是进程的性质,后者是文件本身的性质。

    文件的访问权限

    对于目录,读权限允许我们获得文件列表,执行权限允许我们通过该目录。删除一个文件需要对该文件所在的目录有写权限和执行权限

    内核对于进程的权限判断分为四部,概述为 进程的有效ID是否su-是否是所有者-是否是所有组或附加组成员-其他用户,在各步骤中再确定具体的权限。

    对于创建的新文件,其文件的所有者ID被设置为当前进程有效用户ID,其所属组ID被设置为当前进程的有效组ID其所在目录的组ID。

    access function

    #include <unistd.h>

    int access(const char *pathname, int mode);

    本函数以实际用户ID和实际组ID进行访问权限测试;mode分为R_OK, W_OK, X_OK, F_OK(文件是否存在)。

    umask function

    #include <sys/stat.h>

    mode_t umask(mode_t cmask);

    注意,无出错返回!cmask由9种访问权限位运算而成,分别是:

    S_IRUSR, S_IWUSR, S_IXUSR

    S_IRGRP, S_IWGRP, S_IXGRP

    S_IROTH, S_IWOTH, S_IXOTH

    注意创建的是屏蔽位(就是不能有的位)。umask修改的是创建文件的默认权限,这个改动只在该进程内有效,而不影响shell中的umask值

    在shell中可以获得符号形式的表达,语法是 umask –S。

    chmod, fchmod function

    #include <sys/stat.h>

    int chmod(const char *pathname, mode_t mode);

    int fchmod(int filedes, mode_t mode);

    更改权限的函数,和shell中用法一致。对应符号常量包括:

    S_ISUID, S_ISGID, S_ISVTX(保存正文)

    S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR

    S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP

    S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH

    其中S_ISVTX是SUS扩展选项。

    chmod修改的是i节点最近一次被修改的时间。

    chown,fchown,lchown function

    #include <unistd.h>

    int chown(const char *pathname, uid_t owner, gid_t group);

    int fchwon(int filedes, uid_t owner, gid_t group);

    int lchown(const char *pathname, uid_t owner, gid_t group) //SUS;

    如果是符号链接,最后一个更改链接的拥有者,其他两个更改链接文件的拥有者。

    如果owner或group任一个为-1,那么对应的ID不变。

    _POSIX_CHOWN_RESTRICTED宏规定是否允许任意用户更改其所有文件的所有者。如果=1,那么非root是不能更改文件所属用户和用户组的(除非改到自己这一组)。

    文件长度

    st_size字段只对reg, dir 和link有效。link的长度指的是文件名中的实际字节数。

    文件截短

    #include <unistd.h>

    int truncate(const char *pathname, off_t length);

    int ftruncate(int filedes, off_t length);

    截短一个文件,使其长度为length字节,大于的部分会被截去;如果文件本身小于length,反过来会扩展该文件(取决于实现,SUS扩展行为)

    文件系统

    这块的内容比较难理解,注意硬链接和符号链接的区别,注意文件夹链接和文件链接的区别。

    link, unlink, remove和rename

    #include <unistd.h>

    int link(const char *existingpath, const char *newpath);

    int unlink(const char *pathname)

    使用unlink可以在打开状态下取消链接,即使程序崩溃,临时文件也会被删除。

    root可以unlink一个目录,但是不推荐这么干,用rmdir更好

    #include <stdio.h>

    int remove(const char *pathname);

    int rename(const char *oldname,const char *newname)

    在unix中remove和unlink效果是一样的,但是在非Unix环境下会直接删除文件。

    rename可能会遇到newname已经存在的情况,其行为比较复杂。

    符号链接

    类似于win下的快捷方式,有些函数可以跟踪符号链接,有些则处理符号链接自身,注意分辨。

    符号链接可能引起循环引用问题,简单来说,在一个文件夹中建立一个指向这个文件夹自身的快捷方式,跟踪降序遍历这个文件夹就会得到循环引用的结果。

    循环引用可以通过unlink函数消除,但是硬链接就不行了,所以非super user是不能建立文件夹硬链接的。

    题外话:win下也可以搞类似的玩意,但是没有GUI接口。

    symlink, readlink function

    #include <unistd.h>

    int symlink(const char *actualpath, const char *sympathy)

    sszie_t readlink(const char * restrict pathname, char *restrict buf, size_t bufsize)

    注意symlink不需要actualpath实际存在

    readlink是读取链接本身的字符串的,注意buf中的字符串不以null结尾。

    文件的时间

    st_atime    last access time        ls –u        e.g.: read

    st_mtime    last modify time    default        e.g.: write

    st_ctime    I node last change time    ls –c        e.g.: chmod, chown

    注意系统并不保存对i节点的最后一次访问时间,所以access函数和stat函数对文件本身并无影响。

    很多函数不仅影响文件本身的时间,还会影响其父文件夹的相关量。

    utime function

    #include <utime.h>

    int utime(const char *pathname, const struct utimbuf *time);

    struct utimbuf{

        time_t actime;    //atime

        time_t modtime;//mtime

    };

    修改时间,这里是日历时间(从1970年1月1日到现在的秒数),如果time是空指针,修改atime和mtime到当前时间。用户需要写权限或者set_uid;如果time非空,需要su或者set_uid。

    ctime无法手动更新,调用utime时会自动更新(换言之,没啥能阻挡i节点更新的)。

    mkdir, rmdir function

    #include <sys/stat.h>

    int mkdir(const char *pathname, mode_t mode);

    #include <unistd.h>

    int rmdir(const char *pathname);

    很蛋碎的是不在同一个头文件中=。=

    rmdir处理的文件夹必须是空的,否则失败。

    读目录

    由于Unix各种实现的差别,以及历史相关的原因,现在目录读取函数有一大堆,posix.1规定了如下函数用于目录读取:

    #include <dirent.h>

    DIR *opendir(const char *pathname);

    struct dirent *readdir(DIR *dp);

    void rewinddir(DIR *dp);

    int closedir(DIR *dp);

    long telldir(DIR *dp);    //SUS

    void seekdir(DIR *dp, long dc);    //SUS

    struct dirent{

        ino_t d_ino; //i-node number, SUS

        char d_name[NAME_MAX+1];    //null-terminated filename

    };

    注意NUME_MAX需要运行时确定(fpathconf)。

    题外话:这里编译4-21的时候发现找不到path_alloc,实际在./apue.2e/lib中,也可以用grep –R –include='*.c' path_alloc . 找到该文件。

    chdir, fchdir, getcwd

    #include <unistd.h>

    int chdir(const char *pathname);

    int fchdir(int filedes);    //SUS

    更改当前工作目录。

    在shell中用pwd查看当前目录。

    内核为每个进程保持当前目录信息,但是并不保存完整路径名,可以使用

    char *getcwd(char *buf,size_t size);

    来获得当前绝对路径。如果保存路径是为了返回,还有一种更简单的方法,使用open打开当前目录,然后使用fchdir再返回当前目录。

    设备特殊文件

    在struct stat中,有st_dev和st_rdev这两个dev_t值,前者标识文件系统的设备号,后者包含实际设备的设备号(只有chr和blk文件才有)。

    文件系统的设备号包含主设备号和次设备号,前者标识设备驱动,后者才标定特定的主设备。可以使用宏major和minor来访问主次设备号。

     

    习题:

    注意4.4 creat会清空原来文件的内容,但是不改变已有文件的访问权限。

    4.6 复制前先测试是否是空洞(缓冲区+逐字符),这里要求不是很清晰,可以复制空洞(用lseek)或者直接跳过空洞。

  • 相关阅读:
    python接口自动化问题解决
    python+selenium之测试报告自动化测试实例
    python+selenium之邮件发送
    python+selenium之测试报告
    Python自动发动邮件
    安卓下H5弹窗display:table的bug
    IOS中position:fixed弹出框中的input出现光标错位的问题
    display:table-cell的应用
    :after伪类+content经典应用举例
    不同CSS技术及其CSS性能
  • 原文地址:https://www.cnblogs.com/livewithnorest/p/2863349.html
Copyright © 2011-2022 走看看