Created
June 2, 2021 21:18
-
-
Save Daniel-Abrecht/a46aedeb750fcd1fe9550ce74eb977dc to your computer and use it in GitHub Desktop.
Ringbuffer using memory mapping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ringbuffer.h" | |
#include <stdio.h> | |
#include <string.h> | |
int main(){ | |
char* buf = ringbuffer_create("Hello World ringbuffer"); | |
strcpy(buf+ring_buffer_size-6, "Hello "); | |
strcpy(buf, "World!"); | |
printf("%s\n", buf+ring_buffer_size-6); | |
ringbuffer_destroy(buf); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: | |
gcc -std=c11 -Wall -Wextra -Werror -pedantic main.c ringbuffer.c -o hello |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include "ringbuffer.h" | |
intptr_t ring_buffer_size; | |
intptr_t ring_buffer_mask; | |
__attribute__((constructor(200),used)) | |
static void init_ringbuffers(){ | |
ring_buffer_size = sysconf(_SC_PAGESIZE); | |
ring_buffer_mask = ring_buffer_size - 1; | |
} | |
void* ringbuffer_create(const char* name){ | |
const int fd = memfd_create(name, MFD_CLOEXEC); | |
if(fd == -1){ | |
perror("memfd_create"); | |
return 0; | |
} | |
if(ftruncate(fd, ring_buffer_size) == -1){ | |
perror("ftruncate"); | |
close(fd); | |
return 0; | |
} | |
// Allocate any 2 free pages |A|B| | |
char*const mem = mmap(0, ring_buffer_size*2, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); | |
if(mem == MAP_FAILED){ | |
perror("mmap 1"); | |
close(fd); | |
return 0; | |
} | |
// Replace them with the same one |C|B| | |
if(mmap(mem, ring_buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0) == MAP_FAILED){ | |
perror("mmap 2"); | |
munmap(mem, ring_buffer_size*2); | |
close(fd); | |
return 0; | |
} | |
// Replace them with the same one |C|C| | |
if(mmap(mem+ring_buffer_size, ring_buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0) == MAP_FAILED){ | |
perror("mmap 3"); | |
munmap(mem, ring_buffer_size*2); | |
close(fd); | |
return 0; | |
} | |
close(fd); | |
return mem; | |
} | |
void ringbuffer_destroy(void* ringbuffer){ | |
munmap(ringbuffer, ring_buffer_size*2); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef KITSU_RINGBUFFER_H | |
#define KITSU_RINGBUFFER_H | |
#include <stdint.h> | |
extern intptr_t ring_buffer_size; | |
extern intptr_t ring_buffer_mask; | |
void* ringbuffer_create(const char* name); | |
void ringbuffer_destroy(void* ringbuffer); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment