C语言 – 多个文件保存时的内存处理
本文最后更新于 308 天前,其中的信息可能已经有所发展或是发生改变。
/*
时间:2023/09/12
作者:马文杰
代码功能:存储文件之前,检查内存使用百分比,内存使用超过80%会自动删除最老旧的文件,以此来保证系统正常运行
函数名称: getLogUsePercentage / findMatchingFile / compareFileNames  / delOldLogFile / main

历史:  
    日期:2023/09/21
    作者:mawenjie
    修改:函数delOldLogFile中有一处没有释放资源,是在combinedTime 申请资源失败时没有释放,文中已有记录标记。
*/

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

/*
函数功能: 获取系统指定路径下内存使用的百分比
*/
int getLogUsePercentage()
{
    int iUsePcent = -1;
    char line[512] = {0};

    // 执行df命令并读取输出
    FILE* pipe = popen("df /home/delphi/solo", "r");
    if (pipe == NULL)
    {
        perror("Failed to execute df command");
        exit(EXIT_FAILURE);
    }

    // 读取df命令的输出
    while(fgets(line, sizeof(line), pipe));
    printf("[+][%s:%d] line: %s\n",__FUNCTION__,__LINE__,line);  // "56%"

    pclose(pipe);

    // 解析输出并提取百分比信息
    sscanf(line, "%*s %*s %*s %*s %d%%", &iUsePcent);

    printf("[+][%s:%d] iUsePcent: %d\n",__FUNCTION__,__LINE__,iUsePcent);

    return iUsePcent;
}

/*
函数功能: 字符串匹配,根据字符串的一部分,匹配到一个完整的字符串(文件名称)
*/
char* findMatchingFile(const char* directory, const char* searchString) 
{
    DIR* dir = opendir(directory);
    if (dir == NULL) 
    {
        printf("[+][%s:%d] 无法打开目录: %s\n",__FUNCTION__,__LINE__,directory);
        return NULL;
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL) 
    {
        if (entry->d_type == DT_REG)  // 只处理普通文件
        {
            char* fileName = entry->d_name;
            if (strstr(fileName, searchString) != NULL) // 匹配文件名
            { 
                char* filePath = malloc(strlen(directory) + strlen(fileName) + 2); // 分配足够的内存来存储文件路径
                if (filePath == NULL) 
                {
                    closedir(dir);
                    retturn NULL;
                }

                sprintf(filePath, "%s/%s", directory, fileName);
                closedir(dir);
                printf("[+][%s:%d] 匹配到的文件路径: %s\n",__FUNCTION__,__LINE__,filePath);
                return filePath;
            }
        }
    }

    closedir(dir);
    return NULL; // 没有找到匹配的文件
}

/*
函数功能: qsort排序的规则
*/
int compareFileNames(const void* a, const void* b) 
{
    return strcmp(*(const char**)a, *(const char**)b);
}

/*
函数功能: 删除旧的文件,保证存储文件之前,空间是足够的
*/
void delOldLogFile(void) 
{
    // 删除路径下最老的文件
    const char* logPath = "/home/delphi/solo";
    char* combinedTime = NULL;
    int i = 0;
    struct dirent* entry;
    char** fileNames = NULL;
    int numFiles = 0;

    DIR* dir = opendir(logPath);
    if (dir == NULL) 
    {
        printf("[+][%s:%d] 无法打开目录: %s\n",__FUNCTION__,__LINE__,logPath);
        return;
    }

    while ((entry = readdir(dir)) != NULL) 
    {
        if (entry->d_type == DT_REG) // 只处理普通文件
        {  
            char* fileName = entry->d_name;
            if (strstr(fileName, ".log") != NULL) // 只处理以.log结尾的文件
            {  
                char* timePart = strtok(fileName, "_"); // 提取文件名中的时间部分
                if (timePart != NULL) 
                {
                    // 判断文件名的数字部分的时间
                    char* secondPart = strtok(NULL, "_"); // 提取文件名中的第二部分
                    if (secondPart != NULL) 
                    {
                        combinedTime = malloc(strlen(timePart) + strlen(secondPart) + 2); // 分配足够的内存来存储两个部分的时间
                        if (combinedTime == NULL)
                        {
                            closedir(dir); /* 2023/09/21修改 */
                             return;
                        }

                        strcpy(combinedTime, timePart);
                        strcat(combinedTime, secondPart);

                        long long fileTime = atoll(combinedTime); 
                        printf("[+][%s:%d] 文件组装: %s  文件转换成longlong类型:%d\n",__FUNCTION__,__LINE__,combinedTime,fileTime);

                        if (fileTime != 0) 
                        {
                            fileNames = realloc(fileNames, (numFiles + 1) * sizeof(char*));
                            fileNames[numFiles] = strdup(combinedTime); 
                            numFiles++;

                        }
                        free(combinedTime);
                    }
                }
            }
        }
    }

    closedir(dir);

    if (numFiles == 0) 
    {
        printf("[+][%s:%d] 目录: %s 中没有日志文件\n",__FUNCTION__,__LINE__,logPath);
        return;
    }

    // 按文件名进行排序
    qsort(fileNames, numFiles, sizeof(char*), compareFileNames);

    // 看一下这个排序之后的输出结果对不对
    for (i = 0; i < numFiles; i++)
        printf("[+] 排序结果fileNames:%s\n",fileNames[i]);

    // 获取最老的文件名
    char* oldestFileNameNum = fileNames[0];

    // 打印最老的文件名 20231201221202 -> 20231201_221202
    char oldFileName[16]; 
    strncpy(oldFileName, oldestFileNameNum, 8);
    oldFileName[8] = '_'; 
    oldFileName[9] = '\0'; 
    strcat(oldFileName, oldestFileNameNum + 8);
    printf("[+][%s:%d] 获取最老的文件名:%s\n",__FUNCTION__,__LINE__,oldFileName);
    // 这个文件还需要再文件夹中遍历,找到匹配的文件 20231201_221202 -> 20231201_221202_syslog_user.log
    const char* directory = "/home/delphi/solo";

    char* oldestFilePath = findMatchingFile(directory, oldFileName);
    if (oldestFilePath != NULL) 
    {
        printf("即将删除的文件: %s\n", oldestFilePath);
        remove(oldestFilePath);
        free(oldestFilePath);
    } 
    else 
    {
        printf("未找到匹配的文件\n");
    }

    // 释放内存
    for (i = 0; i < numFiles; i++) 
    {
        free(fileNames[i]);
    }
    free(fileNames);

    return;
}

/*
函数功能:存储文件之前,检查内存使用概率,内存使用超过80%会自动删除最老旧的文件,以此来保证系统正常运行
*/
int main() 
{
    int iUsePcent = -1;
    iUsePcent = getLogUsePercentage();

    // 读取文件名称并删除旧文件,直到剩余空间达到20%
    if(iUsePcent > 80)
        printf("剩余空间不足,读取文件名称并删除旧文件\n");

    while (iUsePcent > 80) 
    {
        // TODO: 在此处添加读取文件名称和删除旧文件的代码
        delOldLogFile();

        // 更新使用的百分比
        iUsePcent = getLogUsePercentage(); 
    }

    // 保存文件
    printf("剩余空间足够,保存文件\n");
    // ...

    return 0;
}

评论

  1. 博主
    Windows Edge 116.0.1938.81
    10 月前
    2023-9-21 11:21:16

    修改:函数delOldLogFile中有一处没有释放资源

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇