开发中和linux命令功能相对应的一些函数整理

system函数

使用 system()函数可以很方便地在我们的程序当中执行任意 shell 命令,本小节来学习下 system()函数的用法,以及介绍 system()函数的实现方法。
首先来看看 system()函数原型,如下所示:
#include <stdlib.h>
int system(const char *command);

这是一个库函数,使用该函数需要包含头文件<stdlib.h>。
函数参数和返回值含义如下:
command:参数 command 指向需要执行的 shell 命令,以字符串的形式提供,譬如"ls -al"、"echo HelloWorld"等。
system()函数其内部的是通过调用 fork()、execl()以及 waitpid()这三个函数来实现它的功能,首先 system()会调用 fork()创建一个子进程来运行 shell(可以把这个子进程成为 shell 进程),并通过 shell 执行参数command 所指定的命令。譬如:

system("ls -la")
system("echo HelloWorld")

system()的返回值如下:
⚫ 当参数 command 为 NULL,如果 shell 可用则返回一个非 0 值,若不可用则返回 0;针对一些非UNIX 系统,该系统上可能是没有 shell 的,这样就会导致 shell 不可能;如果 command 参数不为NULL,则返回值从以下的各种情况所决定。
⚫ 如果无法创建子进程或无法获取子进程的终止状态,那么 system()返回-1;
⚫ 如果子进程不能执行 shell,则 system()的返回值就好像是子进程通过调用_exit(127)终止了;
⚫ 如果所有的系统调用都成功,system()函数会返回执行 command 的 shell 进程的终止状态。
system()的主要优点在于使用上方便简单,编程时无需自己处理对 fork()、exec 函数、waitpid()以及 exit()等调用细节,system()内部会代为处理;当然这些优点通常是以牺牲效率为代价的,使用 system()运行 shell命令需要至少创建两个进程,一个进程用于运行 shell、另外一个或多个进程则用于运行参数 command 中解析出来的命令,每一个命令都会调用一次 exec 函数来执行;所以从这里可以看出,使用 system()函数其效率会大打折扣,如果我们的程序对效率或速度有所要求,那么建议大家不是直接使用 system()。一般情况下均可使用。

 检查文件权限access

文件的权限检查不单单只讨论文件本身的权限,还需要涉及到文件所在目录的权限,只有同时都满足了,才能通过操作系统的权限检查,进而才可以对文件进行相关操作;所以,程序当中对文件进行相关操作之前,需要先检查执行进程的用户是否对该文件拥有相应的权限。那如何检查呢?可以使用 access 系统调用,函数原型如下:

#include <unistd.h>
int access(const char *pathname, int mode);

函数参数和返回值含义如下:

pathname需要进行权限检查的文件路径。

mode该参数可以取以下值:

⚫ F_OK:检查文件是否存在

⚫ R_OK:检查是否拥有读权限

⚫ W_OK:检查是否拥有写权限

⚫ X_OK:检查是否拥有执行权限

除了可以单独使用之外,还可以通过按位或运算符" | "组合在一起。

返回值:检查项通过则返回 0,表示拥有相应的权限并且文件存在;否则返回-1,如果多个检查项组合在一起,只要其中任何一项不通过都会返回-1。

简单示例如下:

mkdir函数

mkdir 函数用于在文件系统中创建一个新的目录。以下是该函数的详细说明:

函数原型

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

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

参数说明

  • pathname: 要创建的目录路径名。

  • mode: 设置新创建目录的访问权限。常用的权限掩码包括:

    • S_IRWXU: 用户读、写和执行权限(00700)。

    • S_IRUSR (S_IREAD): 用户可读权限(00400)。

    • S_IWUSR (S_IWRITE): 用户可写权限(00200)。

    • S_IXUSR (S_IEXEC): 用户执行权限(00100)。

    • S_IRWXG: 组读、写和执行权限(00070)。

    • S_IRGRP: 组可读权限(00040)。

    • S_IWGRP: 组可写权限(00020)。

    • S_IXGRP: 组执行权限(00010)。

    • S_IRWXO: 其他用户读、写和执行权限(00007)。

    • S_IROTH: 其他用户可读权限(00004)。

    • S_IWOTH: 其他用户可写权限(00002)。

    • S_IXOTH: 其他用户执行权限(00001)。

返回值

  • 成功时返回 0

  • 失败时返回 -1,并将错误记录到全局变量 errno 中。

示例代码

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

int main() {
    const char *path = "/path/to/new_directory";
    int res = mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // 设置权限为775

    if (res == -1) {
        perror("Error creating directory");
        return errno;
    }
    printf("Directory created successfully
");
    return 0;
}

注意事项

  1. 权限问题:确保你有权限在指定路径下创建目录。

  2. 错误处理:使用 perrorstrerror(errno) 来获取详细的错误信息。

  3. 递归创建:如果需要递归创建嵌套目录,可以使用自定义函数逐级创建每个目录。

  4. 跨平台兼容性:不同操作系统上的实现可能有所不同。例如,Windows系统使用 _mkdir 函数。

opendir函数

opendir 是一个用于打开目录的函数,通常在 C 语言中使用。该函数定义在 <dirent.h> 头文件中。opendir 返回一个指向 DIR 类型对象的指针,该对象可以用于遍历目录中的文件和子目录。

以下是 opendir 函数的基本用法:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

int main() {
    const char *path = "."; // 当前目录
    DIR *dir;
    struct dirent *entry;

    // 打开目录
    dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return EXIT_FAILURE;
    }

    // 读取目录中的每个条目
    while ((entry = readdir(dir)) != NULL) {
        printf("%s", entry->d_name);
    }

    // 关闭目录
    closedir(dir);

    return EXIT_SUCCESS;
}

在这个示例中:

  1. opendir 函数被用来打开指定路径的目录。如果成功,它返回一个指向 DIR 结构体的指针;如果失败,则返回 NULL 并设置 errno

  2. readdir 函数被用来读取目录中的一个条目(文件或子目录)。每次调用 readdir 都会返回下一个条目,直到没有更多条目为止。

  3. closedir 函数被用来关闭之前打开的目录。

参数

  • const char *path: 要打开的目录的路径。如果传递 ".", 表示当前目录;传递 "..", 表示父目录。

返回值

  • 成功时返回一个指向 DIR 结构体的指针,该结构体可以用来访问目录内容。

  • 失败时返回 NULL,并设置 errno 以指示错误原因。

错误处理

常见的错误包括路径不存在、权限不足等。可以通过 perror 函数打印详细的错误信息。

注意事项

  • 确保在使用完目录后调用 closedir 来释放资源。

  • 使用 readdir 读取目录内容时,要注意处理可能的错误情况,例如目录中途被修改等。

ftw函数

ftw(File Tree Walk)函数是一个用于遍历目录树的函数,定义在 <ftw.h> 头文件中。它通过递归的方式遍历指定目录下的所有文件和子目录,并对每个文件或子目录调用用户提供的回调函数进行处理。

以下是 ftw 函数的基本用法:

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

// 用户定义的回调函数
int my_callback(const char *filepath, const struct stat *info, int type, struct FTW *pathinfo) {
    printf("File: %s", filepath);
    return 0; // 返回0继续遍历,返回非0停止遍历
}

int main() {
    const char *path = "."; // 当前目录

    // 调用ftw函数遍历目录树
    if (ftw(path, my_callback) == -1) {
        perror("ftw");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

在这个示例中:

  1. my_callback 是用户定义的回调函数,每次 ftw 遇到一个文件或子目录时都会调用这个函数。

  2. ftw 函数被用来遍历指定路径的目录树。如果成功,它会返回0;如果失败,则返回-1并设置 errno

参数

  • const char *path: 要遍历的目录路径。如果传递 ".", 表示当前目录;传递 "..", 表示父目录。

  • int (*callback)(const char *filepath, const struct stat *info, int type, struct FTW *pathinfo): 用户提供的回调函数,每当遍历到一个文件或子目录时都会调用这个函数。

回调函数参数

  • const char *filepath: 当前文件或子目录的路径。

  • const struct stat *info: 指向 stat 结构体的指针,包含文件的状态信息。

  • int type: 文件类型,可能是以下几种:

    • FTW_D: 目录。

    • FTW_DNR: 不可读目录。

    • FTW_DP: 符号链接指向的目录。

    • FTW_F: 普通文件。

    • FTW_NS: 无法访问的文件。

    • FTW_SL: 符号链接。

    • FTW_SLN: 不可读的符号链接。

  • struct FTW *pathinfo: 指向 FTW 结构体的指针,包含了额外的信息。

返回值

  • 成功时返回0。

  • 失败时返回-1,并设置 errno 以指示错误原因。

注意事项

  • 确保回调函数正确处理各种文件类型和错误情况。

  • ftw 不会自动处理符号链接,对于符号链接需要特别小心,以免陷入无限循环。

补充:

ftw(dir, cb ,1000)

ftw 函数的第三个参数是 nopenfd,它指定了在遍历目录树时可以同时打开的文件描述符的最大数量。这个参数用于限制并发打开的文件数,以避免资源耗尽的问题。

unlink函数

unlink函数是一个用于删除文件的系统调用。以下是关于unlink函数的具体介绍:

  1. 函数原型

    1. 头文件:#include <unistd.h>。

    2. 函数原型:int unlink(const char *pathname)。

    3. 参数说明:pathname是要删除的文件路径,可以是相对路径或绝对路径。

  2. 工作原理

    1. 连接数检查:unlink函数会先检查文件系统中此文件的连接数是否为1,如果不是1说明此文件还有其他链接对象,因此只对此文件的连接数进行减1操作。

    2. 实际删除:若连接数为1,并且在此时没有任何进程打开该文件,此内容才会真正地被删除掉。在有进程打开此文件的情况下,则暂时不会删除,直到所有打开该文件的进程都结束时文件就会被删除。

  3. 返回值

    1. 成功:成功执行时,返回0。

    2. 失败:失败返回-1,并设置相应的错误码。

  4. 使用场景

    1. 文件管理:unlink函数常用于日常文件管理中的文件删除操作。

    2. 临时文件处理:在程序运行过程中可能会产生一些临时文件,使用unlink函数可以方便地将这些临时文件删除。

    3. 数据安全:在某些情况下,为了确保数据安全,需要频繁删除敏感信息的文件。

总的来说,unlink函数是Linux系统中一个非常重要的系统调用,它提供了一种从文件系统中删除文件的方法。在使用unlink函数时,需要注意其对文件连接数的影响以及可能的错误情况。

猜你喜欢

转载自blog.csdn.net/qq_28576837/article/details/143228220