Opening and Closing Memory-Files

To treat a chunk of memory as a file, it must be “opened” and a handle returned for future file reference and interaction. Likewise, the memory-file must be “closed” when you no longer need it. To accomplish these tasks, I’ve crafted the mem_open() and mem_close() functions.

Both of these functions use a mem_file structure, introduced in last week’s Lesson. The mem_open() function swallows a string to represent the memory-file name. It returns a pointer to a mem_file structure upon success, NULL otherwise.

The mem_close() function requires a mem_file structure pointer as an argument. It has no return value.

The following code uses these functions to create a memory-file then close the memory file.

2023_09_02-Lesson-a.c

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

#define DEFAULT_SIZE 2048

struct mem_file {
    void *address;
    char *name;
    int size;
    int offset;
    char *timestamp;
};

/* create a memory file
   input: filename string
   output: pointer to memory file structure,
           NULL on failure
 */
struct mem_file *mem_open(char *fn)
{
    struct mem_file *mem_new;
    time_t now;

    /* error checking */
    if( fn==NULL )
        return(NULL);

    /* allocate storage for memory file structure */
    mem_new = malloc( sizeof(struct mem_file) );
    if( mem_new==NULL )
        return(NULL);

    /* populate structure */
    mem_new->address = malloc( DEFAULT_SIZE );
    if( mem_new->address==NULL )
        return(NULL);
    mem_new->name=fn;        /* set memory file name */
    mem_new->size = 0;        /* set size */
    mem_new->offset = 0;    /* offset/file pointer */
        /* create timestemp */
    time(&now);
    mem_new->timestamp = ctime(&now);

    return(mem_new);
}

/*
   close memory file, free memory
   input: mem_file structure of an open
           memory file
 */
void mem_close(struct mem_file *m)
{
    free(m->address);
    free(m);
}

/* test the memory file functions */
int main()
{
    static char name1[] = "memory file";
    struct mem_file *mfp1;

    mfp1 = mem_open(name1);
    if( mfp1==NULL )
    {
        fprintf(stderr,"Unable to create %s\n",name1);
        exit(1);
    }

    printf("Memory file '%s' created\n",name1);
    printf("Timestamp = %s\n",mfp1->timestamp);

    printf("Press Enter: ");
    getchar();

    mem_close(mfp1);
    printf("Memory file '%s' closed\n",name1);

    return(0);
}

The mem_open() function immediately checks for an empty string and returns NULL when no string is specified:

if( fn==NULL )
    return(NULL);

Next, memory is allocated for the mem_file structure. This step takes place first and, upon success, memory is then allocated for the memory-file itself based upon the value of DEFAULT_SIZE. If either allocation fails, NULL is returned.

The remainder of the mem_open() function assigns values to the members: the filename, the memory_file size, offset, and timestamp string. The mem_file structure’s address is then returned.

The mem_close() function contains only two statements. The first frees the memory-file’s allocated storage, saved in member address. The second statement frees the mem_file structure itself.

The main() function creates a memory-file. It outputs the memory-file’s timestamp, waits for a key press, then closes the memory-file. Here’s sample output:

Memory file 'memory file' created
Timestamp = Sat Sep  2 10:02:13 2023

Press Enter:
Memory file 'memory file' closed

Because these functions worked so well, I decided to modify the code to open a second memory-file. I wanted to ensure that a second memory-file wouldn’t contaminate the first. This code is available on GitHub, and here is its output:

Memory file 'memory file' created
Timestamp = Sat Aug 19 10:05:10 2023

Press Enter:
Memory file 'memory file two' created
Timestamp = Sat Aug 19 10:05:12 2023

Memory file 'memory file' closed
Memory file 'memory file two' closed

The Press Enter prompt helps to ensure that both memory-files don’t have identical timestamps.

Unlike media files, when these memory-files are closed, they’re gone for good. Memory-files don’t linger in memory ready to be re-opened. For that to happen, I’d need to implement a memory-file file system. That’s too much work! My approach here is to mimic file access by using a chunk of memory.

Next week I continue this exploration with functions to write to and read from the memory-file.

Leave a Reply