• LInux系统编程(3)


    取得拓展属性

    1. #include
    2. #include
    3. ssize_t getxattr(const char* path, const char* key, void* value, size_t size);
    4. ssize_t lgetxattr(const char* path, const char* key, void* value, size_t size);
    5. ssize_t fgetxattr(int fd, const char* key, void* value, size_t size);

    执行成功时,getxattr()会从文件path将拓展属性key的值存入value缓冲区,缓冲区的长度为size个字节,并且返回此值的真实大小。

    如果size为0,则不会存入value中,只返回值的大小,让应用程序决定缓冲区的大小,方便进行存储。

    lgetxattr()的行为如同getxattr(),但是当path是一个符合链接时,返回链接本身的(而非连接的目标文件)的拓展属性。

    设定一个拓展属性

    1. #include
    2. #include
    3. int setxattr(const char* path, const char* key, const void* value, size_t size, int flags);
    4. int lsetxattr(const char* path, cosnt char* key, const void* value, size_t size, int flags);
    5. int fsetxattr(int fd, const char* key, const void* value, size_t size, int flags);

    列出文件上的拓展属性

    1. #include
    2. #include
    3. ssize_t listxattr(const char* path, char* list, size_t size);
    4. ssize_t llistxattr(const char* path, char* list, size_t size);
    5. ssize_t flistxattr(int fd, char*list, size_t size);

    执行成功时,listxattr()返回path文件的拓展属性列表,存入list中,函数返回列表的实际大小,以字节为单位。

    每个拓展属性被传入到list并且以NULL字符结尾,如下所示:

    “user.md5_sum\0user.mime_type\0system.posix_acl_default\0

    如果调用时size设置为0,函数返回列表的实际长度。

    llistxattr()的行为如同listxattr(),当path是一个符号连接时,返回的是链接本身(而不是链接的目标文件)有关的拓展属性。

    移除一个拓展属性

    1. #include
    2. #include
    3. int removexattr(const char* path, const char* key);
    4. int lremovexattr(const char* path, const char* key);
    5. int fremovexattr(int fd, const char* key);

    获取当前目录

    1. #include
    2. #include
    3. int main() {
    4. char *cwd;
    5. cwd = getcwd(NULL, 0);
    6. if(cwd) {
    7. printf("%s", cwd);
    8. }
    9. return 0;
    10. }

    LInux的C链接库还提供了一个get_current_dir_name()函数,当buf为NULL而且size=0时,函数如同getcwd()函数

    1. #define _GNU_SOURCE
    2. #include
    3. #include
    4. #include
    5. int main() {
    6. char *cwd;
    7. cwd = get_current_dir_name();
    8. if(cwd) {
    9. printf("%s", cwd);
    10. }
    11. free(cwd);
    12. return 0;
    13. }

    变更当前工作目录

    1. #include
    2. int chdir(const char* path);
    3. int fchdir(int fd);

    chdir()可用于将当前工作目录变更为path所指定的路径名称,可以绝对路径也可以相对路径,fchdir()用于将当前工作目录变更为fd(必须对应到已经打开的目录)所代表的路径名称。

    1. #define _GNU_SOURCE
    2. #include
    3. #include
    4. #include
    5. int main() {
    6. int swd_fd;
    7. swd_fd = open(".", O_RDONLY);
    8. if (swd_fd == -1) {
    9. perror("open");
    10. exit(EXIT_FAILURE);
    11. }
    12. // 变更为不同的目录
    13. ret = chdir(some_other_dir);
    14. if (ret) {
    15. perror("chdir");
    16. exit(EXIT_FAILURE);
    17. }
    18. // 在新目录中进行其他操作
    19. // 返回所保存的目录中
    20. ret = fchdir(swd_fd);
    21. if (ret) {
    22. perror("fchdir");
    23. exit(EXIT_FAILURE);
    24. }
    25. // 关闭所在目录
    26. ret = close(swd_fd);
    27. if (ret) {
    28. perror("close");
    29. exit(EXIT_FAILURE);
    30. }
    31. return 0;
    32. }

     创建目录

    1. #include
    2. #include
    3. int mkdir(const char* path, mode_t mode);

     执行成功时,会创建权限为mode(经过umask修改)的目录path。

    移除目录

    1. #include
    2. int rmdir(const char* path);

    path路径必须是空的,只能包含‘.’和'..‘路径,没有实现rm -r 的递归删除功能,须手动深度搜索,从叶节点开始删除。

     读取一个目录内容

    1. #include
    2. #include
    3. DIR* opendir(const char* name);

    执行成功时,会创建一个目录流,表示name所指定的目录。目录流就是一个信息比较多的文件描述符,代表已经打开的目录,因此可以获取特定目录流后面的文件描述符:

    1. #define _BSD_SOURCE
    2. #include
    3. #include
    4. int dirfd(DIR* dir);

    执行成功时,返回dir目录流的文件描述符。

     从目录流中读取数据

    1. #include
    2. #include
    3. struct dirent* readdir(DIR* dir);

     

    关闭目录流

    1. #include
    2. #include
    3. int closedir(DIR* dir);
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. /**
    8. * find_file_int_dir 从目录path中搜索file的文件
    9. * 存在返回0,否则返回非0
    10. */
    11. int find_file_in_dir(const char* path, const char* file) {
    12. struct dirent* entry;
    13. int ret = 1;
    14. DIR* dir;
    15. dir = opendir(path);
    16. errno = 0; //这句很重要
    17. while((entry = readdir(dir)) != NULL) {
    18. if (!strcmp(entry->d_name, file)) {
    19. ret = 0;
    20. break;
    21. }
    22. }
    23. if (errno && !entry) {
    24. perror("readdir");
    25. }
    26. closedir(dir);
    27. return ret;
    28. }
    29. int main() {
    30. printf("%d\n", find_file_in_dir(".", "test.c"));
    31. printf("%d\n", find_file_in_dir(".", "aaaa"));
    32. return 0;
    33. }

    硬链接

    1. #include
    2. int link(const char* oldpath, const char* newpath);

    调用成功之后,oldpath和newpath会指向同一个文件,无法区分谁是最初的链接。

    符号链接

    1. #include
    2. int symlink(const char* oldpath, const char* newpath);

     解除链接

    1. #include
    2. int unlink(const char* pathname);
    3. #include
    4. int remove(const char* path);

    执行成功时,remove会从文件系统中删除path并且返回0,如果path是一个文件,调用unlink,如果path是一个目录,则调用rmdir()

    移动

    1. #include
    2. int rename(const char* oldpath, const char* newpath);
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. int main(int argc, char** argv) {
    9. int fd, ret;
    10. if (argc < 2) {
    11. fprintf(stderr, "usage: %s < device to eject>\n", argv[0]);
    12. return 1;
    13. }
    14. /**
    15. * 以只读方式打开CD-ROM设备,O_NONBLOCK用于通知内核,即使
    16. * 设备中没有媒体,也要打开设备
    17. */
    18. fd = open(argv[1], O_RDONLY | O_NONBLOCK);
    19. if (fd < 0) {
    20. perror("open");
    21. return 1;
    22. }
    23. /**
    24. * 给CD-ROM设备送出弹出命令
    25. */
    26. ret = ioctl(fd, CDROMEJECT, 0);
    27. if (ret) {
    28. perror("ioctl");
    29. return 1;
    30. }
    31. ret = close(fd);
    32. if (ret) {
    33. perror("close");
    34. return 1;
    35. }
    36. return 0;
    37. }

    初始化inotify

    1. #include
    2. int inotify_init(void);

    加入一个新的监视项目

    1. #include
    2. int inotify_add_watch(int fd, const char* path, uint32_t mask);

    为path文件或者目录添加一个mask所描述的监听项目至fd所表示的inotify实例。

    1. int wd;
    2. wd = inotify_add_watch(fd, "/etc", IN_ACCESS | IN_MODIFY);
    3. if (wd == -1) {
    4. perror("inotify_add_watch");
    5. exit(EXIT_FAILLURE);
    6. }

     此范例会在/etc所在目录上的所有读取和写入加上一个监视项目,如果/etc中任何文件被读取或者写入,inotify会传送一个事件给inotify文件描述符fd,提供给监视描述符wd。

    inotify事件

     

    读取inotify事件

    1. char buf[BUF_LEN]__attribute__((aligned(4)));
    2. ssize_t len, i = 0;
    3. // 读取BUF_LEN个字节的事件
    4. len = read(fd, buf, BUF_LEN);
    5. // 读取每个事件直到读完为止
    6. while(i < len) {
    7. struct inotify_event * event = (struct inotify_event*) &buf[i];
    8. printf("wd=%d mask=%d cookie=%d len=%d dir=%s\n", event->wd,
    9. event->mask, event->cookie,event->len, (event->mask & IN_ISDIR)?"yes":"no");
    10. //如果有一个名称,则输出它
    11. if(event->len)
    12. printf("name=%d\n", event->name);
    13. //将索引更新为下一个事件的开头
    14. i += sizeof(struct inotify_event) + event->len;
    15. }

     因为inotify文件描述符的行为如同一个常规文件,可以使用select,poll,epoll监听。

    1. int wd;
    2. /**
    3. * 只有在/etc/init.d 是一个目录,且他的路径中没有一个部分是符号链接时,
    4. * 才会监视/etc/init.d是否被移动过
    5. */
    6. wd = inotify_add_watch(fd, "/etc/init.d", IN_MOVE_SELF | IN_ONLYDIR | IN_DONT_FOLLOW);
    7. if (wd == -1) {
    8. perror("inotify_add_watch");
    9. }

     移除一个inotify监视项目

    1. #include
    2. int inotify_rm_watch(int fd, uint32_t wd);

    取得事件队列的大小

    1. #include
    2. unsigned int queue_len;
    3. int ret;
    4. ret = ioctl(fd, FIONREAD, &queue_len);
    5. if (ret < 0)
    6. perror("ioctl");
    7. else
    8. printf("%u bytes pending in queue\n", queue_len);

    销毁一个inotify实例

    1. int ret;
    2. // fd 经 inotify_init() 取得
    3. ret = close(fd);
    4. if (fd == -1)

  • 相关阅读:
    【DLoopDetector(C++)】DBow2词袋模型&&loop close学习
    leetcode 21
    k8s中如何使用gpu、gpu资源讲解、nvidia gpu驱动安装
    成为电车销量的“中坚力量”,微小型车不能只有“低价”?
    延迟任务多种实现姿势--中
    PCL1.12+VTK9.1+QT6编译部署
    IDEA配置Maven
    【计算机视觉 | 目标检测】干货:目标检测常见算法介绍合集(一)
    Doris部署 FS_Broker
    基于局部结构特征的图像匹配
  • 原文地址:https://blog.csdn.net/wj617906617/article/details/133950152