[linux] linux c实现共享内存读写操作

IPC_PRIVATE

IPC_PRIVATE 是用于创建新的 System V IPC(Inter-Process Communication,进程间通信)对象的特殊键值。在使用 System V 共享内存、消息队列或信号量时,IPC_PRIVATE 可以作为 key 参数传递给 shmgetmsggetsemget 函数,以创建一个新的 IPC 对象, IPC_PRIVATE可以替换为自己的唯一key

特点

  • 唯一性 :使用 IPC_PRIVATE 创建的 IPC 对象是唯一的,只有创建它的进程及其子进程能够访问。这是因为 IPC_PRIVATE 实际上并不是一个真正的键值,而是一个特殊标识符,指示内核为调用进程创建一个新的、唯一的 IPC 对象。
  • 进程间隔离 :由于 IPC_PRIVATE 创建的对象不依赖于一个全局可见的键值,其他进程无法通过键值访问该对象,除非它们是通过继承的方式(如 fork)获得的。

IPC_PRIVATE 例子

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>

#define SHM_SIZE 1024  // 共享内存大小

int main() {
    // 创建共享内存段
    int shm_id = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);
    if (shm_id == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    // 附加共享内存段
    char *shm_ptr = (char *)shmat(shm_id, NULL, 0);
    if (shm_ptr == (char *)-1) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    // 写入数据到共享内存
    strncpy(shm_ptr, "Hello, Shared Memory!", SHM_SIZE);

    // 创建子进程
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程读取共享内存
        printf("Child process reads: %s\n", shm_ptr);

        // 分离共享内存段
        if (shmdt(shm_ptr) == -1) {
            perror("shmdt");
            exit(EXIT_FAILURE);
        }
        exit(0);
    } else if (pid > 0) {
        // 父进程等待子进程结束
        wait(NULL);

        // 分离共享内存段
        if (shmdt(shm_ptr) == -1) {
            perror("shmdt");
            exit(EXIT_FAILURE);
        }

        // 删除共享内存段
        if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
            perror("shmctl");
            exit(EXIT_FAILURE);
        }
    } else {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    return 0;
}

自定义Key举例

复制代码
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdio.h>
#include <sys/sem.h>

#define DENY_MAC_SHM_SIZE 18  // MAC地址长度为17个字符,加上一个终止符
#define SHM_MAC_INFO_KEY    (0x00260000)
char *g_deny_mac = NULL;
int shm_init(unsigned int key,int shm_id)
{
    //int shm_id = -1;
    void *shm = NULL;
    if(NULL != g_deny_mac) 
    {
        printf("share memory had already init\r\n");
        return 0;
    }
    else
    {
        shm_id = shmget((key_t)SHM_MAC_INFO_KEY,DENY_MAC_SHM_SIZE,IPC_CREAT|0666);
        if(shm_id == -1)
        {
            printf("shmget failed:%s\n",strerror(errno));
            return -1;
        }
        shm = shmat(shm_id,NULL,0);
        g_deny_mac = (char *)shm;
    }
    return 0;
}
int set_deny_mac(char *mac,int len)
{
    int ret = 0;
    void *deny_mac = NULL;
   
    deny_mac = g_deny_mac;
    
    if(mac != NULL)
    {
        
        memcpy(deny_mac,mac,len);
    }
    else
    {
        ret = -1;
    }

    return ret;
}
int get_deny_mac(char *mac, int len)
{
    int ret = -1;
    void *deny_mac = NULL;
    
    deny_mac = g_deny_mac;

    memcpy(mac,g_deny_mac,len);
    if(strlen(mac) == len)
    {
        ret = 0;
    }
    else
    {
        ret = -1;
    }
    
    return ret;
}
void shm_free(int shm_id)
{
    
    void *shm_ptr = shmat(shm_id, NULL, 0);
    if (shm_ptr == (void *)-1) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }
    // 分离共享内存段
    if (shmdt(shm_ptr) == -1) {
        perror("shmdt");
        exit(EXIT_FAILURE);
    }

    // 删除共享内存段
    if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
        perror("shmctl");
        exit(EXIT_FAILURE);
    }

    return ;
}
int main()
{
    char mac[] = "xx:xx:xx:00:00:01";
    char buf[18] = {0};
    int shm_id;

    shm_init(SHM_MAC_INFO_KEY,shm_id);
    get_deny_mac(buf,sizeof(buf));
    printf("buf=%s mac=%s\n",buf,mac); 
    set_deny_mac(mac,18);
    get_deny_mac(buf,18);
    printf("buf=%s mac=%s\n",buf,mac); 
    shm_free(shm_id);
    
    return 0;
}
相关推荐
orion575 小时前
Missing Semester Class1:course overview and introduction of shell
linux
apocelipes7 小时前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
用户1204872216111 小时前
Linux驱动编译与加载
linux·嵌入式
用户8055336980317 小时前
Input 子系统架构:Core、Handler、Driver 三层是怎么协作的
linux·嵌入式
用户8055336980317 小时前
RK-Forge外设系列开篇 - 把板子从「能启动」变成「能用」:Ethernet/SPI/MMC 三个纯接线外设
linux·github·嵌入式
七歌杜金房1 天前
我终于又有了自己的 Linux 电脑
linux·debian·mac
tntxia2 天前
linux curl命令详解_curl详解
linux
扛枪的书生2 天前
Linux 网络管理器用法速查
linux
顺风尿一寸2 天前
Java Socket 内核之旅:从 SocketChannel.read() 到 tcp_recvmsg 与 epoll 的完整调用链路
linux
XIAOHEZIcode3 天前
Ubuntu 终端美化全栈指南:Bash 到 Kitty 踩坑实录
linux·ubuntu·命令行