美文网首页
Linux系统函数

Linux系统函数

作者: D_Major | 来源:发表于2020-03-02 16:14 被阅读0次

    open/close/perror函数

    perror返回错误码errno转译的错误信息, 和输入信息同时输出.
    umask为权限掩码, 可以重置. 如umask为002, 取反后为775, 与上777结果为775, 主要起到不同类型用户(user, group, others)权限过滤的作用.

    // 打开已存在文件
    fd = open("hello.c", O_RDWR); 
    // 新建文件, (0777)&(umask取反)为真实八进制权限
    fd = open("myhello", O_RDWR | O_CREAT, 0777);   
    // 将文件截断为0
    fd = open("myhello", O_RDWR | O_TRUNC);  
    // 创建文件, 如果已存在则截断为0
    fd = open("myhello", O_RDWR | O_CREAT | O_TRUNC, 0644);  
    // 判断文件是否存在, 必须O_CREAT和O_EXCL同时写才能判断
    fd = open("myhello", O_RDWR | O_CREAT | O_EXCL, 0777);  
    if(fd == -1) 
    {
        perror("file open");
        exit(1);
    }
    int ret = close(fd);
    if(ret == -1)   // 关闭也要测试返回码
    {
        perror("file close");
        exit(1);
    }
    

    read/write/lseek函数

    另有read,write,lseek函数, 缓冲区通过malloc或者数组提供. ssize_t是一个有符号数, -1失败/0已读完/>0字节数(每次读buf大小). write时加const的是要写的东西.
    lseek的whence参数有3个宏, SEEK_SET, SEEK_CUR, SEEK_END, 代表文件指针起始的位置, 在这个基础上增加偏移量offset. lseek可以改变文件指针位置, 获取文件长度和向后拓展文件大小.

    ssize_t read(int fd, void *buf, size_t count);
    ssize_t write(int fd, const void *buf, size_t count);
    off_t lseek(int fd, off_t offset, int whence);
    

    read() write()示例

    lseek()示例, 从末尾向后拓展2000个字节,最后必须要执行一次写操作. 如原文件含Hello, Linux!占14个字节, 拓展后为2014个字节, 又执行了一次写"a", 共2015个字节. 最后得到的是一个空洞文件, 无法打印, 占位用(如迅雷下载).
    truncate()函数不用执行写操作.

    stat函数

    stat 文件名输出文件各种元数据, 其中inode号是文件唯一编号.
    inode: Linux系统通过inode号(唯一)访问文件, 索引节点inode保存了文件的元数据, 一般是128或256字节, 每2KB就设置一个inode. Linux通过inode信息得到文件数据所在的block.
    ls -l, rm都是不追踪软链接的, vi是追踪软链接的.

    // 对于软链接, stat(穿透函数)读到的是真实文件大小, lstat读到的只是软链接大小(路径字节数)
    int stat(const char *path, struct stat *buf);
    int fstat(int fd, struct stat *buf);
    int lstat(const char *path, struct stat *buf);
    

    stat函数传出一个结构体, 里面包含各个信息对应的变量.
    其中st_mode共16位, 为4+3+3+3+3, 分别为文件类型+特殊权限位+user权限+group权限+others权限. 通过与上0170000掩码(八进制)可以得到文件类型, 或者类似的与上0000700得到user权限. 文件类型包括套接字, 软连接, 目录, 管道等.

    其他函数

    access(path, W_OK), 返回0代表有写权限
    chmod(path, 0755), 改变文件权限.
    strtol("0755", NULL, 8)将字符串表示的数字转为八进制, 第二个参数无用
    chown(path, uid, gid)改变文件权限, uid和gid可以在/etc/passwd中查看
    truncate(path, length)若length小于文件实际长度截断, 大于则拓展.
    rename(old_path, new_path)重命名文件

    link相关函数

    link(old_path, new_path)创建硬链接, symlink(old_path, new_path)创建软链接. 硬链接就是普通文件, 指同一个文件不同的文件名, 其inode结点值完全相同, 当rm A, rm B...把一个文件所有的文件名都删光, inode结点对应的链接数为0时, 其数据块才会被回收.
    readlink(path, buf, buf_size)读取软链接的内容
    unlink(path)指定文件成为临时文件, 当进程释放该文件后就删除, 示例如下

    dir相关函数

    chdir(path)改变路径
    getcwd(buf, sizeof(buf))输出当前路径
    mkdir(pathname, mode)创建目录, 需要提供权限
    rmdir(pathname)删除空目录
    DIR* opendir(const char* name)打开目录, 成功返回DIR结构指针, 失败返回NULL.
    struct dirent* readdir(DIR* dirp)传入DIR指针, 返回dirent结构体指针. 结构体的d_type成员包含文件类型, 用宏表示(DT_DIR目录, DE_REG普通文件).
    使用strcmp(ptr->d_name, ".")==0来排除根目录, 使用char buf[1024]={0}; sprintf(buf, "%s/%s", root, ptr->d_name)来拼接字符串.

    // 使用如下方式来遍历目录文件数量
    DIR* dir = opendir(root); 
    struct dirent* ptr = NULL;
    while((ptr = readdir(dir)) !=NULL) {
        排除"."和".."; 
        目录则递归; 
        文件则加1;
    }
    closedir(dir)  // 最后一定要关闭目录, 否则无法返回结果
    

    dup/dup2/fcntl

    dup(old_fd)返回文件描述表中没有被占用的最小的文件描述符, 将其指向传入old_fd指向的文件, 返回新分配的fd的编号.
    dup2(old_fd, new_fd)1. 如果new_fd是一个已被打开的fd, 在拷贝前先关闭new_fd, 然后把new_fd指向old_fd指向的文件, 返回new_fd的编号. 2. 如果old_fd和new_fd是同一个fd, 则直接返回old_fd的编号. 本质上是把old_fd处的指针复制给new_fd, 使得二者都指向old_td指向的文件.
    int fcntl(int fd, int cmd, long arg)fcntl可以获取/改变已打开文件的属性, 如读写权限. O_WRONLY文件指针在头部, 会覆盖部分原内容. O_APPEND文件指针在尾部, 会追加在最后.

    int flag = fcntl(fd, F_GETFL, 0) //获取文件状态标记. 
    //使用按位或对权限(整型数)进行操作, 
    //如设置O_APPEND/O_NONBLOCK(追加写和非阻塞)
    flag |= O_APPEND 
    fcntl(fd, F_SETFL, flag) //将修改后的权限设置进去.
    

    相关文章

      网友评论

          本文标题:Linux系统函数

          本文链接:https://www.haomeiwen.com/subject/rplvkhtx.html