LInux系统编程(3)

编程入门 行业动态 更新时间:2024-10-28 17:16:28

LInux<a href=https://www.elefans.com/category/jswz/34/1770742.html style=系统编程(3)"/>

LInux系统编程(3)

取得拓展属性

#include <sys/types.h>
#include <attr/xattr.h>ssize_t getxattr(const char* path, const char* key, void* value, size_t size);
ssize_t lgetxattr(const char* path, const char* key, void* value, size_t size);
ssize_t fgetxattr(int fd, const char* key, void* value, size_t size);

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

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

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

设定一个拓展属性

#include <sys/types.h>
#include <attr/xattr.h>int setxattr(const char* path, const char* key, const void* value, size_t size, int flags);
int lsetxattr(const char* path, cosnt char* key, const void* value, size_t size, int flags);
int fsetxattr(int fd, const char* key, const void* value, size_t size, int flags);

列出文件上的拓展属性

#include <sys/types.h>
#include <attr/xattr.h>ssize_t listxattr(const char* path, char* list, size_t size);
ssize_t llistxattr(const char* path, char* list, size_t size);
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是一个符号连接时,返回的是链接本身(而不是链接的目标文件)有关的拓展属性。

移除一个拓展属性

#include <sys/types.h>
#include <attr/xattr.h>int removexattr(const char* path, const char* key);
int lremovexattr(const char* path, const char* key);
int fremovexattr(int fd, const char* key);

获取当前目录

#include <unistd.h>
#include <stdio.h>int main() {char *cwd;cwd = getcwd(NULL, 0);if(cwd) {printf("%s", cwd);}return 0;
}

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

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {char *cwd;cwd = get_current_dir_name();if(cwd) {printf("%s", cwd);}free(cwd);return 0;
}

变更当前工作目录

#include <unistd.h>int chdir(const char* path);
int fchdir(int fd);

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

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {int swd_fd;swd_fd = open(".", O_RDONLY);if (swd_fd == -1) {perror("open");exit(EXIT_FAILURE);}// 变更为不同的目录ret = chdir(some_other_dir);if (ret) {perror("chdir");exit(EXIT_FAILURE);}// 在新目录中进行其他操作// 返回所保存的目录中ret = fchdir(swd_fd);if (ret) {perror("fchdir");exit(EXIT_FAILURE);}// 关闭所在目录ret = close(swd_fd);if (ret) {perror("close");exit(EXIT_FAILURE);}return 0;
}

 创建目录

#include <sys/types.h>
#include <sys/stat.h>int mkdir(const char* path, mode_t mode);

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

移除目录

#include <unistd.h>int rmdir(const char* path);

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

 读取一个目录内容

#include <sys/types.h>
#include <dirent.h>DIR* opendir(const char* name);

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

#define _BSD_SOURCE
#include <sys/types.h>
#include <dirent.h>int dirfd(DIR* dir);

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

 从目录流中读取数据

#include <sys/types.h>
#include <dirent.h>struct dirent* readdir(DIR* dir);

 

关闭目录流

#include <sys/types.h>
#include <dirent.h>int closedir(DIR* dir);
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>/*** find_file_int_dir  从目录path中搜索file的文件* 存在返回0,否则返回非0
*/
int find_file_in_dir(const char* path, const char* file) {struct dirent* entry;int ret = 1;DIR* dir;dir = opendir(path);errno = 0;  //这句很重要while((entry = readdir(dir)) != NULL) {if (!strcmp(entry->d_name, file)) {ret = 0;break;}}if (errno && !entry) {perror("readdir");}closedir(dir);return ret;
}int main() {printf("%d\n", find_file_in_dir(".", "test.c"));printf("%d\n", find_file_in_dir(".", "aaaa"));return 0;
}

硬链接

#include <unistd.h>int link(const char* oldpath, const char* newpath);

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

符号链接

#include <unistd.h>
int symlink(const char* oldpath, const char* newpath);

 解除链接

#include <unistd.h>
int unlink(const char* pathname);#include <stdio.h>
int remove(const char* path);

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

移动

#include <stdio.h>
int rename(const char* oldpath, const char* newpath);
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
#include <sys/stat.h>int main(int argc, char** argv) {int fd, ret;if (argc < 2) {fprintf(stderr, "usage: %s < device to eject>\n", argv[0]);return 1;}/*** 以只读方式打开CD-ROM设备,O_NONBLOCK用于通知内核,即使* 设备中没有媒体,也要打开设备*/fd = open(argv[1], O_RDONLY | O_NONBLOCK);if (fd < 0) {perror("open");return 1;}/*** 给CD-ROM设备送出弹出命令*/ret = ioctl(fd, CDROMEJECT, 0);if (ret) {perror("ioctl");return 1;}ret = close(fd);if (ret) {perror("close");return 1;}return 0;
}

初始化inotify

#include <inotify.h>
int inotify_init(void);

加入一个新的监视项目

#include <inotify.h>
int inotify_add_watch(int fd, const char* path, uint32_t mask);

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

int wd;
wd = inotify_add_watch(fd, "/etc", IN_ACCESS | IN_MODIFY);
if (wd == -1) {perror("inotify_add_watch");exit(EXIT_FAILLURE);
}

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

inotify事件

 

读取inotify事件

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

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

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

 移除一个inotify监视项目

#include <inotify.h>
int inotify_rm_watch(int fd, uint32_t wd);

取得事件队列的大小

#include <sys/ioctl.h>unsigned int queue_len;
int ret;
ret = ioctl(fd, FIONREAD, &queue_len);
if (ret < 0)perror("ioctl");
elseprintf("%u bytes pending in queue\n", queue_len);

销毁一个inotify实例

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

更多推荐

LInux系统编程(3)

本文发布于:2023-12-04 19:17:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1661961.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:系统   LInux

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!