跟着iMX28x开发套件学linux-08
Posted diskiii
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跟着iMX28x开发套件学linux-08相关的知识,希望对你有一定的参考价值。
八、linux应用编程之六:共享内存
共享内存是进程间通信的一种方法。共享内存实际上是两个进程打开同一段内存,并都映射到进程地址中,这样就类似于malloc了一个内存*ptr,进程A往这个地址中写数据,进程B就可以从这个地址读取到进程A写进去的数据。
使用共享内存有以下步骤:
shm_open():打开或创建一个共享内存。
ftruncate():设置共享内存的大小。
mmap():将共享内存映射到当前进程的地址空间。
*ptr:写入或读取共享内存中的数据。
munmap():取消共享内存在当前进程的映射,为删除共享内存做准备。
shm_unlink():删除共享内存。
函数详细说明
1) 函数原型:int shm_open(const char *name, int oflag, mode_t mode);
输入参数:name,共享内存名; oflag,打开标志位; mode,设置共享内存的权限。
返 回 值:int,成功返回共享内存的文件描述符,失败返回-1;
示 例:fd = shm_open(SHAMNAME,O_CREAT|O_TRUNC|O_RDWR,S_IRUSR|S_IWUSR);
2) 函数原型:int ftruncate(int fd, off_t length);
输入参数:fd,共享内存的文件描述符;length,要设置的大小。
返 回 值:int,成功返回0,失败返回-1。
示 例:ftruncate(fd, SHMSIZE);
3) 函数原型:void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
输入参数:addr,要映射到的内存地址,可以为NULL;length,要映射的大小;prot,对映射存 储区的保护要求;flags,映射标志位;fd,要映射的共享内存的文件描述符;offset, 要映射的字节在共享内存中的偏移量。
返 回 值:void*,无类型指针,与malloc()的返回值类似。若映射失败返回MAP_FAILED。
示 例:ptr = mmap(NULL, SHMSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4) 函数原型:int munmap(void *addr, size_t length);
输入参数:*addr,共享内存在进程中映射的地址;length,映射的字节数。
返 回 值:int,成功返回0,否则返回1;
示 例:munmap(ptr, SHMSIZE);
5) 函数原型:int shm_unlink(const char *name);
输入参数:*name,共享内存名;
返 回 值:成功返回0,失败返回1;
示 例:shm_unlink(SHMNAME);
参数可能取值:
shm_open() |
mmap() |
||
oflag |
O_RDONLY:共享内存以只读方式打开 |
prot |
PROT_READ:映射区可读 |
O_RDWR:共享内存以可读写方式打开 |
PROT_WRITE:映射区可写 |
||
O_CREAT:共享内存不存在才创建 |
PROT_EXEC:映射区可执行 |
||
O_EXCL:如果指定了 O_CREAT,但共享内存已经存在时返回错误 |
PROT_NONE:映射区不可访问 |
||
O_TRUNC:如果共享内存已经存在则将其大小设置为 0 |
flag |
MAP_FIXED:返回值必须等于 addr。因为这不利于移植性,所以不鼓励使用此标志 |
|
mode |
S_IRWXU:所属用户读、写和执行权限 |
MAP_SHARED:多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化 |
|
S_IRUSR :所属用户读权限 |
MAP_PRIVATE:多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化 |
||
S_IWUSR:所属用户写权限 |
|||
S_I W/R USR/GRP/OTH:mode的格式 |
示例代码
进程A代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <fcntl.h> #include <sys/stat.h> #define SHMSIZE 10 #define SHMNAME "shmtest" int main(){ int fd; char *ptr; fd = shm_open(SHMNAME, O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR); if(fd < 0){ fprintf(stderr, "open shm error\\n"); exit(-1); } ftruncate(fd, SHMSIZE); ptr = mmap(NULL, SHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if(ptr == MAP_FAILED){ perror("mmap error\\n"); exit(-1); } *ptr = 18; munmap(ptr, SHMSIZE); shm_unlink(SHMNAME); return 0; }
进程B代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <fcntl.h> #include <sys/stat.h> #define SHMSIZE 10 #define SHMNAME "shmtest" int main(){ int fd; char* ptr = NULL; fd = shm_open(SHMNAME, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR); if(fd <0){ perror("open shm error\\n"); exit(-1); } ftruncate(fd, SHMSIZE); ptr = mmap(NULL, SHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if(ptr<0){ perror("map shm error\\n"); exit(-1); } while(*ptr != 18){ sleep(1); } printf("ptr : %d\\n", *ptr); munmap(ptr, SHMSIZE); shm_unlink(SHMNAME); return 0; }
运行结果,先后台运行进程B,再运行进程A:
进程B用函数shm_open()创建了名为shmtest的共享内存,然后调用ftruncate()函数对共享内存设置大小,接着调用mmap()函数,将共享内存映射到进程B的地址空间中,while死循环检查共享内存的值是否为18。
接着运行进程A,用shm_open()函数打开进程B创建的shmtest共享内存,然后设置大小,映射到进程A的地址空间中,接着写入18。
进程B接收到进程A写入的18后,输出信息到屏幕,然后终止进程。
PS:需要注意的是,使用了共享内存的程序在编译链接的时候要加上-lrt选项,否则提示shm_open()没有定义。
以上是关于跟着iMX28x开发套件学linux-08的主要内容,如果未能解决你的问题,请参考以下文章
#盲盒+码##跟着小白一起学鸿蒙#如何编译OpenHarmony自带APP