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