Возможная утечка памяти при записи файлов на SD с FAT fs

У меня есть IP-камера с поддержкой HI3516A SoC с гнездом для SD-карт. Операционная система на камере – это обычное ядро ​​Linux 3.4.45. Все работает хорошо, но мне нужно иметь копию видео с камеры на моем удаленном хранилище в Azure, поэтому я написал программу на C, которая захватывает внутренний поток RTP, разбивает его на сегменты, записывает эти сегменты на SD-карту и отправляет их на мое лазурное хранилище.

Я устанавливаю 64 ГБ SD-карту на камеру, создаю FAT fs на ней и монтирую на / mnt / sd_card. Моя программа работает так, как я ожидаю, но после 1 – 3 дней безотказной работы я увидел, что вся оперативная память камеры где-то исчезла.

Прежде всего, я решаю, что у меня есть утечка памяти в моей программе, и убейте ее, используя следующую команду:

kill -S SIGKILL 1223 

но память не вернулась к системе. Я думаю, странное поведение. Через несколько дней после исправления ошибок я неожиданно обнаружил, что после того, как я отключу SD-карту, вся память вернется обратно в систему. Теперь я решаю, какие у меня ошибки в части создания файла в моей программе. Чтобы проверить этот случай, я написал следующую программу:

 #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; } 

То, что у меня было до начала моих тестов:

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

Теперь я запустил свой тестовый код и попросил его создать 10 МБ файлов на SD-карте

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

и в другом окне я начинаю контролировать свою память

 ~ # 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 

Только 2 МБ свободной оперативной памяти. Теперь я останавливаю свой код и отключаю SD-карту и просматриваю статус памяти

 /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 

Итак, может кто-нибудь объяснить мне, что происходит? Я думаю, что Linux резервирует некоторую память для буферов, чтобы убедиться, что все данные будут записаны на SD-карту, но когда моя программа остановится, память не освобождается, пока не отключите SD-карту.

Заранее спасибо.

Interesting Posts

Что может пойти не так, если / var / tmp находится во временной файловой системе?

Различные версии одного и того же lib нарушили мой менеджер пакетов

Хранить массив в файл и загружать массив из файла в BASH

Какая база данных использует `updatedb` и` locate`?

Невозможно установить 32-битный gstreamer-ffmpeg, библиотека не может найти другие 32-разрядные библиотеки

Исключение файла в цикле bash

По умолчанию для автоматической настройки обновлений включена линия. Для чего это?

Псевдо-файлы для временных данных

Как сделать значения столбца разделенным запятой?

Переопределяемые функции в Zsh

Удаленный файл по-прежнему остается таким же на медиа-устройстве, которое я смонтировал

Установка раздела Windows без разрешения на выполнение

Как я могу удалить все символы, попадающие под / * … * / includes / * & * /?

Файл / usr / libexec / mysqld не существует или не является исполняемым.

Как настроить mail.log на PHP?

Linux и Unix - лучшая ОС в мире.