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