Skip to content

Instantly share code, notes, and snippets.

@Daniel-Abrecht
Created June 2, 2021 21:18
Show Gist options
  • Save Daniel-Abrecht/a46aedeb750fcd1fe9550ce74eb977dc to your computer and use it in GitHub Desktop.
Save Daniel-Abrecht/a46aedeb750fcd1fe9550ce74eb977dc to your computer and use it in GitHub Desktop.
Ringbuffer using memory mapping
#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);
}
all:
gcc -std=c11 -Wall -Wextra -Werror -pedantic main.c ringbuffer.c -o hello
#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);
}
#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