From ddc93e90e36d78d110b4168768ce49c4d06e80f8 Mon Sep 17 00:00:00 2001 From: cheliequan <liequanche@126.com> Date: 星期五, 02 十二月 2022 17:02:15 +0800 Subject: [PATCH] init memfd --- src/memfd.c | 254 +++++++++++++++++++++++++++++++ include/memfd.h | 20 ++ sample/sample_open.c | 64 ++++++++ src/CMakeLists.txt | 11 + sample/CMakeLists.txt | 18 ++ sample/sample_create.c | 89 +++++++++++ CMakeLists.txt | 5 7 files changed, 461 insertions(+), 0 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8f90a2a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.9) +project(memfd) +add_subdirectory(src) +add_subdirectory(sample) + diff --git a/include/memfd.h b/include/memfd.h new file mode 100644 index 0000000..79c0808 --- /dev/null +++ b/include/memfd.h @@ -0,0 +1,20 @@ + +#ifndef MEMFD_H +#define MEMFD_H +#include "unistd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int basic_shm_create(char *name, ssize_t len); +int basic_shm_open(int fd, pid_t pid, int flags); +int basic_shm_mmap(int fd, unsigned char** ppaddr); +int basic_shm_unmmap(int fd, unsigned char** ppaddr); +int basic_shm_close(int fd); +int basic_shm_shrink(int fd, ssize_t len); +int basic_shm_grow(int fd, ssize_t len); +#ifdef __cplusplus +} +#endif +#endif diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt new file mode 100644 index 0000000..e0a93a4 --- /dev/null +++ b/sample/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.9) +file(GLOB SOURCES *.c) + +include_directories(../include) + +# add binary +add_executable(sample_create sample_create.c) +add_executable(sample_open sample_open.c) + +target_link_libraries(sample_create + PRIVATE + memfd + ) +target_link_libraries(sample_open + PRIVATE + memfd + ) + diff --git a/sample/sample_create.c b/sample/sample_create.c new file mode 100644 index 0000000..36e51fd --- /dev/null +++ b/sample/sample_create.c @@ -0,0 +1,89 @@ +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/stat.h> +#include "memfd.h" + +#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ +} while (0) + +int main(int argc, char *argv[]) +{ + int fd; + char *name; + ssize_t i, len; + unsigned char* paddr; + struct stat st; + int ret = 0; + + if (argc < 3) { + fprintf(stderr, "%s name size\n", argv[0]); + exit(EXIT_FAILURE); + } + + name = argv[1]; + len = atoi(argv[2]) * 1024LU * 1024LU * 1024LU; + + /* Create an anonymous file in tmpfs; */ + + fd = basic_shm_create(name, len); + + if (fd == -1) + errExit("memfd_create"); + + /* Size the file as specified on the command line */ + + ret = basic_shm_mmap (fd, &paddr); + if (ret < 0) + errExit("basic_shm_mmap"); + + for (i = 0; i < len; ++i) + paddr[i] = i & 0x000000FF; + + if (fstat (fd, &st)) + errExit ("fstat"); + + printf("length: %zu, atime: %lu.%lu\n", len, st.st_atim.tv_sec, st.st_atim.tv_nsec); + fprintf(stderr, "pid:%d,fd:%d\n", getpid(), fd); + + /* Keep running, so that the file created by memfd_create() + continues to exist */ + + + sleep (120); + //pause(); + + printf("length: %zu, atime: %lu.%lu\n", len, st.st_atim.tv_sec, st.st_atim.tv_nsec); + ret = basic_shm_unmmap(fd, &paddr); + if (ret < 0) + errExit("basic_shm_unmmap"); + + + /*open to test again*/ + fd = basic_shm_open(fd, 0, 0); + if (fd <= 0) + errExit("basic_shm_open"); + + ret = basic_shm_mmap (fd, &paddr); + if (ret < 0) + errExit("basic_shm_mmap"); + + printf ("start: "); + for (i = 0; i < 32; ++i) + printf ("%i ", paddr[i]); + printf ("\nend: "); + for (i = 0; i < 32; ++i) + printf ("%i ", paddr[len-32+i]); + printf ("\ndone\n"); + + ret = basic_shm_unmmap(fd, &paddr); + if (ret < 0) + errExit("basic_shm_unmmap"); + + basic_shm_close(fd); + + exit(EXIT_SUCCESS); +} diff --git a/sample/sample_open.c b/sample/sample_open.c new file mode 100644 index 0000000..8c991ee --- /dev/null +++ b/sample/sample_open.c @@ -0,0 +1,64 @@ +#include <sys/stat.h> +#include <stdlib.h> +#include <stdio.h> +#include "memfd.h" +#include <errno.h> +#include <stdio.h> + +#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ +} while (0) + +int main(int argc, char *argv[]) +{ + ssize_t i, len; + unsigned char* paddr; + struct stat st; + pid_t pid = 0; + int fd = 0; + int ret = 0; + + if (argc != 3) { + fprintf(stderr, "%s PID FD\n", argv[0]); + exit(EXIT_FAILURE); + } + + pid = atol(argv[1]); + fd = atol(argv[2]); + + fd = basic_shm_open(fd, pid, 1); + if (fd <= 0) + { + errExit("basic_shm_open"); + } + + + if (fstat (fd, &st)) + errExit ("fstat"); + + + len = st.st_size; + + printf("length: %zu, atime: %lu.%lu\n", len, st.st_atim.tv_sec, st.st_atim.tv_nsec); + + ret = basic_shm_mmap(fd, &paddr); + if (ret < 0) + errExit("basic_shm_mmap"); + + printf ("start: "); + for (i = 0; i < 32; ++i) + printf ("%i ", paddr[i]); + printf ("\nend: "); + for (i = 0; i < 32; ++i) + printf ("%i ", paddr[len-32+i]); + printf ("\ndone\n"); + + ret = basic_shm_unmmap(fd, &paddr); + if (ret < 0) + errExit("basic_shm_unmmap"); + + basic_shm_close(fd); + + pause(); + + exit(EXIT_SUCCESS); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..8079e0e --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.9) + +file(GLOB SOURCES *.c) + +include_directories(../include) + +# add library +add_library(memfd SHARED memfd.c) + + + diff --git a/src/memfd.c b/src/memfd.c new file mode 100644 index 0000000..0cc3fb9 --- /dev/null +++ b/src/memfd.c @@ -0,0 +1,254 @@ +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/syscall.h> +#include <errno.h> +#include <fcntl.h> +#include <linux/memfd.h> +#include <stdlib.h> +#include <time.h> +#include <stdarg.h> + +#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ +} while (0) + +#define LOGFILE "/opt/vasystem/valog/memfd.log" + +/***************************************************************************** + 鍑� 鏁� 鍚� : mydebug + 鍔熻兘鎻忚堪 : 鏃ュ織璁板綍鍑芥暟锛岃褰曞埌鏂囦欢 + 杈撳叆鍙傛暟 : const char *fmt + ... + 杈撳嚭鍙傛暟 : 鏃� + 杩� 鍥� 鍊� : 鏃� + 璋冪敤鍑芥暟 : + 琚皟鍑芥暟 : + + 淇敼鍘嗗彶 : + 1.鏃� 鏈� : 2018骞�1鏈�15鏃� + 浣� 鑰� : cheliequan + 淇敼鍐呭 : 鏂扮敓鎴愬嚱鏁� + +*****************************************************************************/ +void mydebug(const char *fmt, ...) +{ + char debugbuff[2048]; + int outlen; + FILE *fp; + va_list ap; + time_t nowtime = time(NULL); + struct tm *pNowtime=NULL; + pNowtime = localtime(&nowtime); + + fp=fopen(LOGFILE,"a+"); + if(fp==NULL) + { + return; + } + va_start(ap, fmt); + outlen=vsprintf(debugbuff,fmt,ap); + va_end(ap); + *(debugbuff+outlen) = 0; + fprintf(fp,"%d-%02d-%02d %02d:%02d:%02d====",pNowtime->tm_year+1900,pNowtime->tm_mon+1,pNowtime->tm_mday,pNowtime->tm_hour,pNowtime->tm_min,pNowtime->tm_sec); + fprintf(fp,"%s",debugbuff); + fclose(fp); +} + +static int sys_memfd_create(const char *name, + unsigned int flags) +{ + return syscall(__NR_memfd_create, name, flags); +} + +int basic_shm_create(char *name, ssize_t len) +{ + int fd; + struct stat st; + + /* Create an anonymous file in tmpfs; */ + + fd = sys_memfd_create(name, MFD_CLOEXEC); + + if (fd == -1) + { + errExit("memfd_create"); + } + + /* Size the file as specified on the command line */ + + mydebug("length: %zu\n", len); + if (ftruncate(fd, len) == -1) + { + errExit("truncate"); + } + + if (fstat (fd, &st)) + { + errExit ("fstat"); + } + + mydebug("PID: %ld; fd: %d; /proc/%ld/fd/%d, atime: %lu.%lu\n", + (long) getpid(), fd, (long) getpid(), fd, st.st_atim.tv_sec, st.st_atim.tv_nsec); + + return fd; +} + + +int basic_shm_path_open(int memfd, pid_t pid) +{ + ssize_t len; + int fd; + struct stat st; + if ((pid != 0) && (memfd != 0)) + { + char fd_path[512] = {0}; + snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", pid, memfd); + + fd = open(fd_path, O_RDWR|O_CLOEXEC); + if (fd == -1) + { + errExit("open"); + } + } + + if (fstat (fd, &st)) + { + errExit ("fstat"); + } + len = st.st_size; + + mydebug("length: %zu, atime: %lu.%lu\n", len, st.st_atim.tv_sec, st.st_atim.tv_nsec); + + return fd; +} + +int basic_shm_open(int fd, pid_t pid, int flags) +{ + if(0 >= flags) + { + basic_shm_path_open(fd, getpid()); + } + else + { + basic_shm_path_open(fd, pid); + } +} + +int basic_shm_mmap(int fd, unsigned char** ppaddr) +{ + struct stat st; + ssize_t len; + if (fstat (fd, &st)) + { + errExit ("fstat"); + } + len = st.st_size; + + *ppaddr = (unsigned char*) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (*ppaddr == MAP_FAILED) + { + errExit("mmap"); + } + + mydebug("length: %zu, atime: %lu.%lu\n", len, st.st_atim.tv_sec, st.st_atim.tv_nsec); + return len; +} + +int basic_shm_unmmap(int fd, unsigned char** ppaddr) +{ + struct stat st; + ssize_t len; + int ret = 0; + if (fstat (fd, &st)) + { + errExit ("fstat"); + } + len = st.st_size; + + ret = munmap(*ppaddr, len); + if (ret == -1) + { + errExit("munmap()"); + } + + mydebug("length: %zu, atime: %lu.%lu\n", len, st.st_atim.tv_sec, st.st_atim.tv_nsec); + return len; +} + +int basic_shm_close(int fd) +{ + if (fd >= 0) + { + close(fd); + } +} + +static void mfd_assert_size(int fd, size_t size) +{ + struct stat st; + int r; + + r = fstat(fd, &st); + if (r < 0) { + mydebug("fstat(%d) failed: %m\n", fd); + } else if (st.st_size != size) { + mydebug("wrong file size %lld, but expected %lld\n", + (long long)st.st_size, (long long)size); + } +} + +static int mfd_assert_open(int fd, int flags, mode_t mode) +{ + char buf[512]; + int r; + + sprintf(buf, "/proc/self/fd/%d", fd); + r = open(buf, flags, mode); + if (r < 0) + { + mydebug("open(%s) failed: %m\n", buf); + } + + return r; +} + +int basic_shm_shrink(int fd, ssize_t len) +{ + int r, fd2; + + r = ftruncate(fd, len); + if (r < 0) { + mydebug("ftruncate(SHRINK) failed\n"); + return r; + } + + mfd_assert_size(fd, len); + + fd2 = mfd_assert_open(fd, + O_RDWR | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR); + if (fd2 < 0) { + mydebug("basic_shm_shrink failed\n"); + return fd2; + } + + return fd2; +} + +int basic_shm_grow(int fd, ssize_t len) +{ + int r; + + r = ftruncate(fd, len); + if (r < 0) { + mydebug("ftruncate(GROW) failed: %m\n"); + return r; + } + + mfd_assert_size(fd, len); + + return r; +} -- Gitblit v1.8.0