IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【Linux C】POSIX 共享内存使用 -> 正文阅读

[系统运维]【Linux C】POSIX 共享内存使用

POSIX 共享内存能够让无关进程共享一个映射区域而无需创建一个相应的映射文件,Linux 内核从 2.4 起开始支持 POSIX 共享内存。Linux 使用挂载于 /dev/shm 目录下的专用 tmpfs 文件系统,这个文件系统具有内核持久性——它所包含的共享内存对象会一直持久,即使当前不存在任何进程打开它,但这些对象会在系统关闭后丢失。

共享内存区域占据的内存总量受限于底层的 tmpfs 文件系统的大小,这个文件系统通常会在启动时使用默认大小进行挂载。如果有必要的话,超级用户能够通过命令 mount -o remount,size=<num-bytes>重新挂载这个文件系统来修改它的大小。

编译步骤,需要链接 -lrt,比如:sudo gcc pshm_create.c -o pshm_create -lrt

创建

int shm_open(const char *name, int oflag, mode_t mode);

name 参数标识出了待创建或待打开的共享内存对象;oflag 参数是一个改变调用行为的位掩码;mode参数与该内存对象的所有权和组所有权有关,mode参数能取的位值与文件上的权限位值是一样的。

oflag:

  • O_CREAT 对象不存在时创建对象
  • O_EXCLO_CREAT 互斥地创建对象,如果 O_CREAT 也被设置,能够确保调用者是对象的创建者,如果对象已经存在,那么就返回一个错误
  • O_RDONLY 打开只读访问
  • O_RDWR 打开读写访问
  • O_TRUNC 将对象长度截断为 0

如果 oflag 参数中不包含 O_CREAT,那么就打开一个既有对象,如果指定了 O_CREAT,那么就在对象不存在时创建对象。

// POSIX share mem
// sudo gcc pshm_create.c -o pshm_create -lrt

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <getopt.h>

// int shm_open(const char *name, int oflag, mode_t mode);

static void usageError(const char *progName)
{
	fprintf(stderr, "Usage: %s [-cx] name size [octal-perms]\n", progName);
	fprintf(stderr, "\t-c Create sharedmemory (O_CREAT)\n");
	fprintf(stderr, "\t-x Create exclusively (O_EXCL)\n");
	exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
	int flags, opt, fd;
	mode_t perms;
	long long int size; // size_t size;
	void *addr;

	flags = O_RDWR;
	while((opt = getopt(argc, argv, "cx")) != -1)
	{
		switch(opt)
		{
			case 'c': flags |= O_CREAT; break;
			case 'x': flags |= O_EXCL; break;
			default: usageError(argv[0]);
		}	
	}	
	// printf("argc=%d, optind=%d\n", argc, optind);
	if(optind + 1 >= argc)
		usageError(argv[0]);
	size = atol(argv[optind+1]);
	perms = S_IRUSR | S_IWUSR;
	// printf("%lld\n", size);
	
	// create shared memory object and set its size

	fd = shm_open(argv[optind], flags, perms);
	if(fd == -1)
		exit(EXIT_FAILURE);
	
	if(ftruncate(fd, size) == -1)
		exit(EXIT_FAILURE);

	// map shared memory object

	addr = mmap(NULL,size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if(addr == MAP_FAILED)
		exit(EXIT_FAILURE);
	
	exit(EXIT_SUCCESS);
}

创建一个长度 1000 字节的共享内存对象,然后在 /dev/shm 中使用 ls 命令显出了这个对象。
在这里插入图片描述

写入

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <getopt.h>
#include <string.h>

int main(int argc, char *argv[])
{
	int fd;
	long long int len; // size of shared memory object
	char *addr;

	if(argc != 3 || strcmp(argv[1], "--help") == 0)
	{
		printf("%s shm-name string\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	fd = shm_open(argv[1], O_RDWR, 0);	// open
	if(fd == -1)
		exit(EXIT_FAILURE);
	
	len = strlen(argv[2]);
	if(ftruncate(fd, len) == -1)	// resize with strlen()
		exit(EXIT_FAILURE);
	printf("Resized to %ld bytes\n", (long)len);
	
	addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if(addr == MAP_FAILED)
		exit(EXIT_FAILURE);
	
	if(close(fd) == -1)
		exit(EXIT_FAILURE);
	
	printf("copying %ld bytes\n", (long)len);
	memcpy(addr, argv[2], len);	// write to shm
	exit(EXIT_SUCCESS);
}

向共享内存对象 demo_shm 写入字符 hello。共享对象大小变为 5 的原因是 ftruncate() 系统调用根据写入内容的长度改变共享对象大小的缘故。
在这里插入图片描述

读出

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <getopt.h>
#include <string.h>


int main(int argc, char *argv[])
{
	int fd;
	char *addr;
	struct stat sb;

	if(argc != 2 || strcmp(argv[1], "--help") == 0)
	{
		printf("%s shm-name string\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	fd = shm_open(argv[1], O_RDONLY, 0);	// open
	if(fd == -1)
		exit(EXIT_FAILURE);
	
	if(fstat(fd, &sb) == -1) // fstat 由文件描述词取得文件状态
		exit(EXIT_FAILURE);
	
	addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
	if(addr == MAP_FAILED)
		exit(EXIT_FAILURE);
	
	if(close(fd) == -1)
		exit(EXIT_FAILURE);
	
	write(STDOUT_FILENO, addr, sb.st_size);
	printf("\n");
	exit(EXIT_SUCCESS);
}

在这里插入图片描述

删除

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <getopt.h>
#include <string.h>

int main(int argc, char *argv[])
{

	if(argc != 2 || strcmp(argv[1], "--help") == 0)
	{
		printf("%s shm-name string\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	
	if(shm_unlink(argv[1]) == -1)
		exit(EXIT_FAILURE);
	
	exit(EXIT_SUCCESS);
}

在这里插入图片描述

在其它程序中使用工具

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#define SHM_NAME "demo_shm"
#define CREATE_SCRIPT "pshm_unlink"
int main(int argc, char *argv[])
{
	char cmd[50] = {0};
	sprintf(cmd, "./%s %s ", CREATE_SCRIPT, SHM_NAME);
	printf("%s\n", cmd);
	system(cmd);
	exit(0);
}
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 12:11:44  更:2022-02-26 12:14:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 5:44:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码