我有一个基于 HI3516A SoC 的 IP 摄像机,带有 SD 卡插槽。相机上的操作系统是定制的3.4.45 Linux内核。一切正常,但我需要在 Azure 中的远程存储上有来自摄像机的视频副本,因此,我用 C 语言编写了程序,捕获内部 RTP 流,将其分割成段,将这些段写入 SD 卡并将它们发送到我的 Azure 存储。
我已将 64GB SD 卡安装到相机上,在其上创建 FAT fs 并安装到 /mnt/sd_card。我的程序按我的预期工作,但在正常运行 1 - 3 天后,我发现相机的所有 RAM 都消失在某处。
首先,我确定程序中存在内存泄漏,并使用下一个命令终止它:
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
现在,我运行测试代码,并要求它在 SD 卡上创建 10 MB 文件
/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 MB 的可用 RAM。现在我停止代码并卸载 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卡。
提前致谢。