【linuxl】inux随记--共享内存

该文详细介绍了System-V接口下的共享内存机制,包括shmget()、shmat()、shmdt()和shmctl()等关键函数的使用,并结合信号量实现进程间的同步。在示例代码中,展示了如何创建共享内存、映射及解除映射,并通过信号量控制对共享内存的访问,确保数据的安全传输。

system-v 共享内存

作用:高效率传输大量数据
共享内存用法
  • 定义一个唯一的key//ftok()
  • 构造一个共享内存对象//shmget()
  • 共享内存映射//shmat()
  • 解除共享内存映射//shmdt()
  • 删除共享内存//shmctl() RMID
shmget() :获取共享内存对象的ID
int shmget(key_t key, size_t size, int shmflg);

参数说明:

  • key:标识共享内存的键值
  • size:要创建共享内存的大小,所有的内存分配操作都是以页为单位的,所以即使只申请只有一个字节的内存,内存也会分配整整一页。
  • shmflg:
    • IPC_CREAT:共享内存不存在则创建。
    • mode:共享内存的权限

返回值:

成功:共享内存ID

失败:-1

shmat() 映射函数:映射共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg);

参数:

  • shmid:共享内存id
  • shmaddr:映射地址,NULL为自动分配
  • shmflg:
    • SHM_RDONLY:只读方式映射
    • 0:可读可写

返回值:

成功:共享内存首地址

失败:-1

shmdt函数:解除共享内存映射
int shmdt(const void *shmaddr);

参数:

  • shaddr:映射地址

返回值:

成功:0

失败:-1

shmctl函数:获取或设置共享内存相关属性
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • shmid:共享内存id
  • cmd:
    • IPC_STAT:获取共享内存的属性信息
    • IPC_SET:设置共享内存的属性
    • IPC_RMID:删除共享内存
  • buf:用于设置或获取属性信息的数组,IPC_RMID 为:NULL

返回值:

成功:0

失败:-1

main.c
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include "sem.h"

#define DELAY_TIME 1 /* 为了突出演示效果,等待几秒钟, */

int main(void)
{
    pid_t result;
    int sem_id;
    int shm_id;
    char *addr;
   char buf[1024] = "hello world";
    sem_id = semget((key_t)666, 1, 0666 | IPC_CREAT); /* 创建一个信号量*/
    shm_id = shmget((key_t)7777,1024,0666 | IPC_CREAT);

    init_sem(sem_id, 0);

    /*调用 fork()函数*/
    result = fork();
  
    if(result == -1)
    {
        perror("Fork\n");
    }
    else if (result == 0) /*返回值为 0 代表子进程*/
    {
        printf("Child process will wait for some seconds...\n");
        sleep(DELAY_TIME);
        
        addr = (char*)shmat(shm_id,NULL,0);
        if(addr == (void*)-1)
        {
            printf("shmat child error\r\n");
            exit(-1);
        }
        while(1)
        {
            sleep(DELAY_TIME);
            printf("enter data into shared memory:");
            memset(buf,0,1024);
            if(fgets(buf,10,stdin) == NULL)
            {
                printf("fgets error\r\n");
                exit(-1);
            }
            
            memcpy(addr,buf,strlen(buf));
            //到支路进行v+操作,也叫信号量释放,这就保证了子进程执行在父进程前面,也就是同步。
            sem_v(sem_id);
         }
        exit(0);
    }
    else /*返回值大于 0 代表父进程*/
    { 
        while(1)
       {
            sem_p(sem_id);
            printf("get sem\r\n");
            //信号为o不能进行p-操作,代码执行到这会阻塞,直到子进程释放信号量。
            addr = shmat(shm_id,NULL,0);
            if(addr == (void*)-1)
            {
                printf("shmat parent error\r\n");
                exit(-1);
            }
            printf("shared memory string:%s",addr);
        }

        shmdt(addr);

        shmctl(shm_id,IPC_RMID,NULL);

        sem_v(sem_id);
        del_sem(sem_id);
        exit(0);
    }
   return 0;
}

其他文件 sem.h sem.c跟system-V 信号量中的文件一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值