首页 > 系统相关 >(七)Linux系统其他函数

(七)Linux系统其他函数

时间:2022-10-27 20:34:27浏览次数:98  
标签:函数 int study 系统 fd Linux cpp include root

1 文件属性操作函数

  • 判断文件是否存在及权限
    int access(const char *pathname, int mode);

access.c

/*
    #include <unistd.h>
    int access(const char *pathname, int mode);
        作用:判断某个文件是否有某个权限,或者判断文件是否存在
        参数:
            - pathname: 判断的文件路径
            - mode:
                R_OK: 判断是否有读权限
                W_OK: 判断是否有写权限
                X_OK: 判断是否有执行权限
                F_OK: 判断文件是否存在
        返回值:成功返回0, 失败返回-1
*/

#include <unistd.h>
#include <stdio.h>

int main() {

    int ret = access("a.txt", F_OK);
    if(ret == -1) {
        perror("access");
        return -1;
    }

    printf("文件存在!\n");

    return 0;
}

运行示例代码。

root@LDY:~/cpp-study/lesson13# gcc access.c -o access
root@LDY:~/cpp-study/lesson13# ./access 
文件存在!
  • 修改文件权限
    int chmod(const char *filename, int mode);

chmod.c

/*
    #include <sys/stat.h>
    int chmod(const char *pathname, mode_t mode);
        修改文件的权限
        参数:
            - pathname: 需要修改的文件的路径
            - mode:需要修改的权限值,八进制的数
        返回值:成功返回0,失败返回-1
*/
#include <sys/stat.h>
#include <stdio.h>
int main() {

    int ret = chmod("a.txt", 0777);

    if(ret == -1) {
        perror("chmod");
        return -1;
    }

    return 0;
}

运行示例代码,修改 a.txt 。

root@LDY:~/cpp-study/lesson13# ll a.txt 
-rw-r--r-- 1 root root 0 Oct 26 19:36 a.txt
root@LDY:~/cpp-study/lesson13# gcc chmod.c -o chmod
root@LDY:~/cpp-study/lesson13# ./chmod
root@LDY:~/cpp-study/lesson13# ll a.txt
-rwxrwxrwx 1 root root 0 Oct 26 19:36 a.txt*
  • 修改文件所有者和所在组
    int chown(const char *path, uid_t owner, gid_t group);
    用户id在/etc/passwd
    组id在/etc/group

  • 改变文件大小
    int truncate(const char *path, off_t length);

truncate.c

/*
    #include <unistd.h>
    #include <sys/types.h>
    int truncate(const char *path, off_t length);
        作用:缩减或者扩展文件的尺寸至指定的大小
        参数:
            - path: 需要修改的文件的路径
            - length: 需要最终文件变成的大小
        返回值:
            成功返回0, 失败返回-1
*/

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

int main() {

    int ret = truncate("b.txt", 5);

    if(ret == -1) {
        perror("truncate");
        return -1;
    }

    return 0;
}

运行示例代码。

root@LDY:~/cpp-study/lesson13# ll b.txt
-rw-r--r-- 1 root root 11 Oct 26 19:54 b.txt
root@LDY:~/cpp-study/lesson13# gcc truncate.c -o truncate
root@LDY:~/cpp-study/lesson13# ./truncate
root@LDY:~/cpp-study/lesson13# ll b.txt
-rw-r--r-- 1 root root 5 Oct 26 19:57 b.txt

2 目录操作函数

  • 创建目录
    int mkdir(const char *pathname, mode_t mode);

    最终权限需要和umask相与,拥有可执行权限才能进入目录

mkdir.c

/*
    #include <sys/stat.h>
    #include <sys/types.h>
    int mkdir(const char *pathname, mode_t mode);
        作用:创建一个目录
        参数:
            pathname: 创建的目录的路径
            mode: 权限,八进制的数
        返回值:
            成功返回0, 失败返回-1
*/

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

int main() {

    int ret = mkdir("aaa", 0777);

    if(ret == -1) {
        perror("mkdir");
        return -1;
    }

    return 0;
}

运行示例代码。

root@LDY:~/cpp-study/lesson14# gcc mkdir.c -o mkdir
root@LDY:~/cpp-study/lesson14# ./mkdir 
root@LDY:~/cpp-study/lesson14# ls
aaa  mkdir  mkdir.c
root@LDY:~/cpp-study/lesson14# 
  • 删除空目录
    int rmdir(const char *pathname);
  • 重命名目录
    int rename(const char *oldpath, const char *newpath);

rename.c

/*
    #include <stdio.h>
    int rename(const char *oldpath, const char *newpath);
        作用:重命名目录
        参数:
            oldpath: 原路径
            newpath: 新路径
        返回值:
            成功返回0, 失败返回-1
*/
#include <stdio.h>

int main() {

    int ret = rename("aaa", "bbb");

    if(ret == -1) {
        perror("rename");
        return -1;
    }

    return 0;
}

运行示例代码。

root@LDY:~/cpp-study/lesson14# gcc rename.c -o rename
root@LDY:~/cpp-study/lesson14# ./rename 
root@LDY:~/cpp-study/lesson14# ls
bbb  mkdir  mkdir.c  rename  rename.c
  • 更改当前工作目录
    int chdir(const char *path);
  • 获取当前工作目录
    char *getcwd(char *buf, size_t size);

chdir.c

/*

    #include <unistd.h>
    int chdir(const char *path);
        作用:修改进程的工作目录
            比如在/home/nowcoder 启动了一个可执行程序a.out, 进程的工作目录 /home/nowcoder
        参数:
            path : 需要修改的工作目录
        返回值:
            成功返回0, 失败返回-1

    #include <unistd.h>
    char *getcwd(char *buf, size_t size);
        作用:获取当前工作目录
        参数:
            - buf : 存储的路径,指向的是一个数组(传出参数)
            - size: 数组的大小
        返回值:
            返回的指向的一块内存,这个数据就是第一个参数
*/
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

int main() {

    // 获取当前的工作目录
    char buf[128];
    getcwd(buf, sizeof(buf));
    printf("当前的工作目录是:%s\n", buf);

    // 修改工作目录
    int ret = chdir("/root/cpp-study/lesson14/bbb");
    if(ret == -1) {
        perror("chdir");
        return -1;
    } 

    // 创建一个新的文件
    int fd = open("chdir.txt", O_CREAT | O_RDWR, 0664);
    if(fd == -1) {
        perror("open");
        return -1;
    }

    close(fd);

    // 获取当前的工作目录
    char buf1[128];
    getcwd(buf1, sizeof(buf1));
    printf("当前的工作目录是:%s\n", buf1);
    
    return 0;
}

运行示例代码。

root@LDY:~/cpp-study/lesson14# gcc chdir.c -o chdir
root@LDY:~/cpp-study/lesson14# ./chdir
当前的工作目录是:/root/cpp-study/lesson14
当前的工作目录是:/root/cpp-study/lesson14/bbb
root@LDY:~/cpp-study/lesson14# tree
.
├── bbb
│   └── chdir.txt
├── chdir
├── chdir.c
├── mkdir
├── mkdir.c
├── rename
└── rename.c

1 directory, 7 files

3 目录遍历函数

  • 打开目录
    DIR *opendir(const char *name);
  • 读取目录
    struct dirent *readdir(DIR *dirp);
  • 关闭目录
    int closedir(DIR *dirp);
  • dirent 结构体
    struct dirent
    {
      ino_t d_ino;   // 此目录进入点的inode
      off_t d_off;  // 目录文件开头至此目录进入点的位移
      unsigned short int d_reclen;  // d_name 的长度, 不包含NULL字符
      unsigned char d_type;  // d_name 所指的文件类型
      char d_name[256];  // 文件名
    };
    
  • d_type
    • DT_BLK - 块设备
    • DT_CHR - 字符设备
    • DT_DIR - 目录
    • DT_LNK - 软连接
    • DT_FIFO - 管道
    • DT_REG - 普通文件
    • DT_SOCK - 套接字
    • DT_UNKNOWN - 未知

readFileNum.c统计文件中普通文件个数。

/*
    // 打开一个目录
    #include <sys/types.h>
    #include <dirent.h>
    DIR *opendir(const char *name);
        参数:
            - name: 需要打开的目录的名称
        返回值:
            DIR * 类型,理解为目录流
            错误返回NULL


    // 读取目录中的数据
    #include <dirent.h>
    struct dirent *readdir(DIR *dirp);
        - 参数:dirp是opendir返回的结果
        - 返回值:
            struct dirent,代表读取到的文件的信息
            读取到了末尾或者失败了,返回NULL

    // 关闭目录
    #include <sys/types.h>
    #include <dirent.h>
    int closedir(DIR *dirp);
*/
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int getFileNum(const char * path);

// 读取某个目录下所有的普通文件的个数
int main(int argc, char * argv[]) {

    if(argc < 2) {
        printf("%s path\n", argv[0]);
        return -1;
    }

    int num = getFileNum(argv[1]);

    printf("普通文件的个数为:%d\n", num);

    return 0;
}

// 用于获取目录下所有普通文件的个数
int getFileNum(const char * path) {

    // 1.打开目录
    DIR * dir = opendir(path);

    if(dir == NULL) {
        perror("opendir");
        exit(0);
    }

    struct dirent *ptr;

    // 记录普通文件的个数
    int total = 0;

    while((ptr = readdir(dir)) != NULL) {

        // 获取名称
        char * dname = ptr->d_name;

        // 忽略掉. 和..
        if(strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) {
            continue;
        }

        // 判断是否是普通文件还是目录
        if(ptr->d_type == DT_DIR) {
            // 目录,需要继续读取这个目录
            char newpath[256];
            sprintf(newpath, "%s/%s", path, dname);
            total += getFileNum(newpath);
        }

        if(ptr->d_type == DT_REG) {
            // 普通文件
            total++;
        }


    }

    // 关闭目录
    closedir(dir);

    return total;
}

运行示例代码。

root@LDY:~/cpp-study/lesson15# gcc readFileNum.c -o rfn
root@LDY:~/cpp-study/lesson15# ./rfn /opt
普通文件的个数为:4872

4 dup、dup2函数

  • 复制文件描述符
    int dup(int oldfd);

    指向同一个文件

dup.c

/*
    #include <unistd.h>
    int dup(int oldfd);
        作用:复制一个新的文件描述符
        fd=3, int fd1 = dup(fd),
        fd指向的是a.txt, fd1也是指向a.txt
        从空闲的文件描述符表中找一个最小的,作为新的拷贝的文件描述符
*/

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

int main() {

    int fd = open("a.txt", O_RDWR | O_CREAT, 0664);

    int fd1 = dup(fd);

    if(fd1 == -1) {
        perror("dup");
        return -1;
    }

    printf("fd : %d , fd1 : %d\n", fd, fd1);

    close(fd);

    char * str = "hello,world\n";
    int ret = write(fd1, str, strlen(str));
    if(ret == -1) {
        perror("write");
        return -1;
    }

    close(fd1);

    return 0;
}

运行示例代码,用复制得到的文件描述符向原文件描述符指向的文件写数据。

root@LDY:~/cpp-study/lesson16# gcc dup.c -o dup
root@LDY:~/cpp-study/lesson16# ./dup
fd : 3 , fd1 : 4
root@LDY:~/cpp-study/lesson16# cat a.txt
hello,world
  • 重定向文件描述符
    int dup2(int oldfd, int newfd);

dup2.c

/*
    #include <unistd.h>
    int dup2(int oldfd, int newfd);
        作用:重定向文件描述符
        oldfd 指向 a.txt, newfd 指向 b.txt
        调用函数成功后:newfd 和 b.txt 做close, newfd 指向了 a.txt
        oldfd 必须是一个有效的文件描述符
        oldfd和newfd值相同,相当于什么都没有做
*/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

int main() {

    int fd = open("1.txt", O_RDWR | O_CREAT, 0664);
    if(fd == -1) {
        perror("open");
        return -1;
    }

    int fd1 = open("2.txt", O_RDWR | O_CREAT, 0664);
    if(fd1 == -1) {
        perror("open");
        return -1;
    }

    printf("fd : %d, fd1 : %d\n", fd, fd1);

    int fd2 = dup2(fd, fd1);
    if(fd2 == -1) {
        perror("dup2");
        return -1;
    }

    // 通过fd1去写数据,实际操作的是1.txt,而不是2.txt
    char * str = "hello, dup2\n";
    int len = write(fd1, str, strlen(str));

    if(len == -1) {
        perror("write");
        return -1;
    }

    printf("fd : %d, fd1 : %d, fd2 : %d\n", fd, fd1, fd2);

    close(fd);
    close(fd1);

    return 0;
}

运行示例代码。

root@LDY:~/cpp-study/lesson16# gcc dup2.c -o dup2
root@LDY:~/cpp-study/lesson16# ./dup2
fd : 3, fd1 : 4
fd : 3, fd1 : 4, fd2 : 4
root@LDY:~/cpp-study/lesson16# cat 1.txt
hello, dup2
root@LDY:~/cpp-study/lesson16# cat 2.txt

5 fcntl函数

  • 复制文件描述符,设置/获取文件的状态标志
    int fcntl(int fd, int cmd, ... /* arg */ );

    还有其他功能

fcntl.c

/*
    #include <unistd.h>
    #include <fcntl.h>

    int fcntl(int fd, int cmd, ...);
    参数:
        fd : 表示需要操作的文件描述符
        cmd: 表示对文件描述符进行如何操作
            - F_DUPFD : 复制文件描述符,复制的是第一个参数fd,得到一个新的文件描述符(返回值)
                int ret = fcntl(fd, F_DUPFD);

            - F_GETFL : 获取指定的文件描述符文件状态flag
              获取的flag和我们通过open函数传递的flag是一个东西。

            - F_SETFL : 设置文件描述符文件状态flag
              必选项:O_RDONLY, O_WRONLY, O_RDWR 不可以被修改
              可选性:O_APPEND, O_NONBLOCK
                O_APPEND 表示追加数据
                O_NONBLOK 设置成非阻塞
        
        阻塞和非阻塞:描述的是函数调用的行为。
*/

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

int main() {

    // 1.复制文件描述符
    // int fd = open("1.txt", O_RDONLY);
    // int ret = fcntl(fd, F_DUPFD);

    // 2.修改或者获取文件状态flag
    int fd = open("1.txt", O_RDWR);
    if(fd == -1) {
        perror("open");
        return -1;
    }

    // 获取文件描述符状态flag
    int flag = fcntl(fd, F_GETFL);
    if(flag == -1) {
        perror("fcntl");
        return -1;
    }
    // 不能直接添加新的状态,原来的状态会被替换,
    // 要在原有状态的基础上追加
    flag |= O_APPEND;   // flag = flag | O_APPEND

    // 修改文件描述符状态的flag,给flag加入O_APPEND这个标记
    int ret = fcntl(fd, F_SETFL, flag);
    if(ret == -1) {
        perror("fcntl");
        return -1;
    }

    char * str = "你好\n";
    write(fd, str, strlen(str));

    close(fd);

    return 0;
}

运行示例代码,向文件追加内容。

root@LDY:~/cpp-study/lesson17# gcc fcntl.c -o fcntl
root@LDY:~/cpp-study/lesson17# ./fcntl 
root@LDY:~/cpp-study/lesson17# cat 1.txt
你好

参考链接
https://www.nowcoder.com/study/live/504/1/30

标签:函数,int,study,系统,fd,Linux,cpp,include,root
From: https://www.cnblogs.com/dalelee/p/16829754.html

相关文章