New file |
| | |
| | | cmake_minimum_required(VERSION 3.9) |
| | | project(memfd) |
| | | add_subdirectory(src) |
| | | add_subdirectory(sample) |
| | | |
New file |
| | |
| | | |
| | | #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 |
New file |
| | |
| | | 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 |
| | | ) |
| | | |
New file |
| | |
| | | #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); |
| | | } |
New file |
| | |
| | | #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); |
| | | } |
New file |
| | |
| | | cmake_minimum_required(VERSION 3.9) |
| | | |
| | | file(GLOB SOURCES *.c) |
| | | |
| | | include_directories(../include) |
| | | |
| | | # add library |
| | | add_library(memfd SHARED memfd.c) |
| | | |
| | | |
| | | |
New file |
| | |
| | | #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; |
| | | } |