`

C语言进程间通信(四)——共享内存

 
阅读更多

共享内存通信方式效率最高,毕竟是直接操作内存,但是要保证多个进程对同一块内存访问的同步互斥比较麻烦,借助信号量实现

对每个共享存储段,内核维护一个shmid_ds类型的结构体,定义在<sys/shm.h>文件中

struct shmid_ds
{
struct ipc_perm shm_perm;	//共享内存的ipc_perm结构
size_t shm_segsz;	//共享内存区域大小,字节表示
pid_t shm_lpid;	//最后一次调用shmop函数的进程ID
pid_t shm_cpid;	//创建此共享内存的进程ID
unsigned short shm_lkcnt;	//共享内存被锁定的时间数
unsigned long shm_nattch;	//当前使用共享内存的进程数
time_t shm_atime;	//最后一次附加操作时间
time_t shm_dtime;	//最后一次分离操作时间
time_t shm_ctime;	//最后一次修改时间
}

共享内存基本操作

1,创建或打开一个共享内存(shmget)

//create_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>

#define BUFSZ 1024

int main()
{
        int shm_id;     //共享内存ID
        shm_id = shmget(IPC_PRIVATE,BUFSZ,0666);
        if(shm_id < 0){
                printf("shmget failed\n");
                return -1;
        }
        printf("create shared memory succeed: %d\n",shm_id);
        system("ipcs -m"); //查看共享内存ID
        return 0;
}

2,附加共享内存到进程空间(shmat/shmdt)

//attach_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>

#define BUFSZ 1024

int main()
{
        int *shm;
        shm = shmat(104529925,NULL,0);
        if(*shm == -1){
                printf("shmat failed\n");
                return -1;
        }
        printf("attach shared memory succeed: %d\n",*shm);
        system("ipcs -m"); //查看共享内存调用状态 
        if(shmdt(shm) == -1){
                printf("shmdt failed\n");
                return -1;
        }
        system("ipcs -m"); //查看共享内存调用状态 
        return 0;
}

3,共享内存控制函数(shmctl)

 

下面写个简单的例子

共享内存写端(write_shm.c)

//write_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>

typedef struct
{
        char name[4];
        int age;
}people;

int main()
{
        int i;
        char *t = 'a';
        people *p_shm = NULL;
        p_shm = shmat(104529925,NULL,0);
        if(p_shm == NULL){
                printf("shmat failed\n");
                return -1;
        }
        for(i=0;i<5;i++) {
                t += 1;
                memcpy((*(p_shm+i)).name,&t,1);
                (*(p_shm+i)).age = 20+i;
        }
        if(shmdt(p_shm) == -1){
                printf("shmdt failed\n");
                return -1;
        }
        return 0;
}

共享内存读端(read_shm.c)

//read_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>

typedef struct
{
        char name[4];
        int age;
}people;

int main()
{
        int i;
        char *t = 'a';
        people *p_shm = NULL;
        p_shm = shmat(104529925,NULL,0);
        if(p_shm == NULL){
                printf("shmat failed\n");
                return -1;
        }
        for(i=0;i<5;i++) {
                printf("name:%s age:%d\n",(*(p_shm+i)).name,(*(p_shm+i)).age);
        }
        if(shmdt(p_shm) == -1){
                printf("shmdt failed\n");
                return -1;
        }
        return 0;
}

先后编译执行"写代码"与"读代码",结果如下

root$ ./write_shm.out 
root$ ./read_shm.out 
name:b age:20
name:c age:21
name:d age:22
name:e age:23
name:f age:24
分享到:
评论

相关推荐

    详解Linux进程间通信——使用共享内存

    进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问...

    华清远见嵌入式linux应用程序开发技术详解下载(内部资料).rar

     8.1 Linux下进程间通信概述   8.2 管道通信   8.3 信号通信  8.4 共享内存   8.5 消息队列  8.6 实验内容   本章小结   思考与练习 第9章 多线程编程   9.1 Linux下线程概述   9.2 Linux...

    linux 内核源代码分析

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6. 5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章 基于socket的进程间通信 ...

    Linux内核源代码情景分析 (上下册 高清非扫描 )

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用...

    linux内核源代码情景分析

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用...

    边干边学Linux__第二版_doc格式

    16.1 进程间通信和共享内存 16.2 共享内存的API 16.3 共享内存在Linux中的实现 第17章 同步机制 17.1 同步机制 17.2 Linux中几种同步机制的实现 17.3 设计我们自己的同步机制 第18章 文件系统 18.1 文件系统基本...

    Linux内核情景分析(非扫描版)

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6. 5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 《LINUX内核源代码情景分析(下册)》图书...

    嵌入式Linux应用程序开发标准教程(第2版全)

    接着系统地讲解了嵌入式Linux的环境搭建,以及嵌入式Linux的I/O与文件系统的开发、进程控制开发、进程间通信开发、网络应用开发、基于中断的开发、设备驱动程序的开发以及嵌入式图形界面的开发等,并且还安排了丰富...

    Linux内核情景分析

    第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6. 5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 《LINUX内核源代码情景分析(下册)》图书...

    嵌入式Linux C编程入门(第2版) PPT

    10.3 arm linux进程间通信api 301 10.3.1 管道通信 301 10.3.2 信号通信 303 10.3.3 共享内存 308 10.3.4 消息队列 309 10.4 arm linux线程相关api 312 10.5 linux守护进程 317 10.5.1 守护...

    嵌入式Linux应用程序开发详解

    8.1 Linux下进程间通信概述 240 8.2 管道通信 241 8.2.1 管道概述 241 8.2.2 管道创建与关闭 242 8.2.3 管道读写 244 8.2.4 标准流管道 246 8.2.5 FIFO 249 8.3 信号通信 253 8.3.1 信号...

    Linux程序设计 第4版.haozip01

    第13章 进程间通信:管道 443 13.1 什么是管道 443 13.2 进程管道 444 13.3 将输出送往popen 445 13.3.1 传递更多的数据 446 13.3.2 如何实现popen 447 13.4 pipe调用 449 13.5 父进程和子进程 451 13.5.1 ...

    Linux程序设计 第4版.haozip02

    第13章 进程间通信:管道 443 13.1 什么是管道 443 13.2 进程管道 444 13.3 将输出送往popen 445 13.3.1 传递更多的数据 446 13.3.2 如何实现popen 447 13.4 pipe调用 449 13.5 父进程和子进程 451 13.5.1 ...

    UNIX高级编程 计算机科学丛书

    5. IPC——进程间通信(第十四、十五章)。 6. 实例—一个数据库的函数库(第十六章)、与Postscrip打印机的通信(第十七章)、调制解调器拨号程序(第十八章)以及使用伪终端(第十九章)。 如果对C语言较熟悉并...

    软件工程-理论与实践(许家珆)习题答案

    习 题 答 案 习题一答案 一、选择题 1. 软件的主要特性是(A B C)。 A) 无形 B) 高成本 C) 包括程序和文档  D) 可独立构成计算机系统 2.... A) 技术、方法和工具  B) 方法、工具和过程  ...

Global site tag (gtag.js) - Google Analytics