1

I have a HI3516A SoC based IP camera with SD card slot. The operation system on camera is custom 3.4.45 Linux kernel. Everything works well, but I need to have a copy of video from camera on my remote storage in Azure, so, I wrote program in C what capture internal RTP stream, split it into segments, write this segments to SD card and send them to my Azure storage.

I've install 64GB SD card to my camera, create FAT fs on it and mount to /mnt/sd_card. My program works as I expect, but after 1 - 3 days of uptime I saw that all RAM of camera is disappeared somewhere.

First of all I decide what I have memory leaks in my program and kill it using next command:

kill -S SIGKILL 1223

but memory didn't come back to system. Strange behaviour I think. After some days of bug fixing, I suddenly found what then I unmount SD card all memory returns back to the system. Now, I decide what I have some errors in the part of file creation in my program. To test this case I wrote next programm:

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <limits.h>
#include <inttypes.h>
#include <time.h>

#define KB 1024
#define MB KB * 1024
#define GB MB * 1024


static void print_msg(const char *fmt, ...) {
    va_list args;
    time_t timer = time(NULL);

    printf("%s\t", ctime(&timer));

    va_start(args, fmt);
    vfprintf(stdout, fmt, args);
    va_end(args);
}

static int generate_file(const char *dest_fname, const size_t file_size) {
    char buffer[BUFSIZ];
    const char *source_fname = "/dev/urandom";
    size_t bytes_to_operate, avaliable_bytes = file_size;
    int bytes_readed, bytes_writed, source_fd = -1, dest_fd = -1, rc = EXIT_SUCCESS;


    source_fd = open(source_fname, O_RDONLY);
    if (source_fd < 0) {
        printf("Can't open source file '%s': %s.\n", source_fname, strerror(errno));
        rc = EXIT_FAILURE;
        goto end;
    }

    dest_fd = open(dest_fname, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    if (dest_fd < 0) {
        printf("Can't open destination file '%s': %s.\n", dest_fname, strerror(errno));
        rc = EXIT_FAILURE;
        goto end;
    }

    bytes_to_operate = avaliable_bytes - BUFSIZ;

    print_msg("Write random data to file\n");
    while(avaliable_bytes > 0) {
        bytes_to_operate = (avaliable_bytes > BUFSIZ) 
                ? BUFSIZ
                : avaliable_bytes;

        bytes_readed = read(source_fd, buffer, bytes_to_operate);
        if (bytes_readed < 0) {
            printf("Error while reading data from '%s': %s", source_fname,
                    strerror(errno));
            rc = EXIT_FAILURE;
            goto end;
        }

        if (bytes_readed != bytes_to_operate) {
            // don't read write more than read
            bytes_to_operate = bytes_readed;
        }

        bytes_writed = write(dest_fd, buffer, bytes_to_operate);

        if (bytes_writed < 0) {
            printf("Error while writing data to '%s': %s", dest_fname,
                    strerror(errno));
            rc = EXIT_FAILURE;
            goto end;
        }

        avaliable_bytes -= bytes_writed;
    }

end:
    print_msg("Close file\n");                
    close(source_fd);
    close(dest_fd);

    return rc;
}

static void generate_fpath(char *out, const char *dest_path, uint16_t index) {
    snprintf(out, PATH_MAX, "%s/file_%"SCNu16, dest_path, index);
}

int main(int argc, char** argv) {

    size_t file_size;
    const char *dest_path = argv[3];
    char fpath[PATH_MAX];
    uint16_t del_index = 0, cur_index = 0;

    switch(argv[2][0]) {
        case 'K':
            file_size = atoi(argv[1]) * KB;
            break;
        case 'M':
            file_size = atoi(argv[1]) * MB;
            break;
        default:
            file_size = atoi(argv[1]);
            break;
    } 

    print_msg("Generate files of size %s%s to %s\n", argv[1], argv[2], argv[3]);

    while (cur_index < UINT16_MAX) {
        generate_fpath(fpath, dest_path, cur_index);
        generate_file(fpath, file_size);
        printf("Created file %s\n", fpath);
        cur_index++;
        del_index++;
        sleep(1);
    }

    return EXIT_SUCCESS;
}

What I have before starting my tests:

/mnt # free
             total         used         free       shared      buffers
Mem:        125044        58540        66504            0          480
-/+ buffers:              58060        66984
Swap:            0            0            0

Now, I run my test code, and ask it to create 10 MB files on SD card

/mnt # mount /dev/sd_card2 /mnt/sd_card2
/mnt # ./random_size_file_generator 10 M /mnt/sd_card2

and in another window I start to monitor my memory

~ # free
             total         used         free       shared      buffers
Mem:        125044        60988        64056            0         2180
-/+ buffers:              58808        66236
Swap:            0            0            0
~ # free
             total         used         free       shared      buffers
Mem:        125044        65464        59580            0         2204
-/+ buffers:              63260        61784
Swap:            0            0            0

...

~ # free
             total         used         free       shared      buffers
Mem:        125044       123004         2040            0         1104
-/+ buffers:             121900         3144
Swap:            0            0            0

Only 2 MB of free RAM. Now I stop my code and unmount SD card and look for memory status

/mnt # ./random_size_file_generator 10 /mnt/sd_card2
Created file /mnt/sd_card2/file_0
Created file /mnt/sd_card2/file_1
Created file /mnt/sd_card2/file_2
Created file /mnt/sd_card2/file_3
Created file /mnt/sd_card2/file_4
Created file /mnt/sd_card2/file_5
Created file /mnt/sd_card2/file_6
Created file /mnt/sd_card2/file_7
Created file /mnt/sd_card2/file_8
Created file /mnt/sd_card2/file_9
^C
/mnt # umount /mnt/sd_card2/
/mnt # free
             total         used         free       shared      buffers
Mem:        125044        58500        66544            0          472
-/+ buffers:              58028        67016
Swap:            0            0            0

So, could anybody explain me whats going on? I think, Linux reserve some memory for buffers, to make sure what all data will be written to SD card, but when my program stops, memory don't free until unmount SD card.

Thanks in advance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.