更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
vm_syscall.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "sys/types.h"
33#include "sys/shm.h"
34#include "errno.h"
35#include "unistd.h"
36#include "los_vm_syscall.h"
37#include "fs/file.h"
38
39/**
40 * @brief 系统调用|申请虚拟内存(分配线性地址区间)
41 * \n 鸿蒙与Linux标准库的差异 http://weharmonyos.com/zh-cn/device-dev/kernel/%E4%B8%8ELinux%E6%A0%87%E5%87%86%E5%BA%93%E7%9A%84%E5%B7%AE%E5%BC%82/
42 * @param addr 用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),
43 否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。
44 * @param size 内存段的大小。
45 * @param prot 用于设置内存段的访问权限,有如下权限:
46 \n PROT_READ:允许读该内存段。
47 \n PROT_WRITE:允许写该内存段。
48 \n PROT_EXEC:允许执行该内存段。
49 \n PROT_NONE:不能访问。
50 * @param flags 控制程序对内存段的改变所造成的影响,有如下属性:
51 \n MAP_PRIVATE:标志指定线性区中的页可以被进程独享
52 \n MAP_SHARED:标志指定线性区中的页可以被几个进程共享
53 * @param fd 打开的文件描述符,如果新的线性区将把一个文件映射到内存的情况
54 * @param offset 用以改变经共享内存段访问的文件中数据的起始偏移值。
55 * @return void* 成功返回:虚拟内存地址,这地址是页对齐。
56 \n 失败返回:(void *)-1。
57 */
58void *SysMmap(void *addr, size_t size, int prot, int flags, int fd, size_t offset)
59{
60 /* Process fd convert to system global fd */
61 fd = GetAssociatedSystemFd(fd);
62
63 return (void *)LOS_MMap((uintptr_t)addr, size, prot, flags, fd, offset);//分配线性地址区间
64}
65
66/**
67 * @brief 释放虚拟内存
68 * @param addr 虚拟内存起始位置
69 * @param size 内存段的大小
70 * @return int 成功返回0 失败返回-1。
71 */
72int SysMunmap(void *addr, size_t size)
73{
74 return LOS_UnMMap((uintptr_t)addr, size);
75}
76
77/**
78 * @brief
79 * @param oldAddr 需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。
80 * @param oldLen 内存段的原始大小。
81 * @param newLen 新内存段的大小。
82 * @param flags 如果没有足够的空间在当前位置展开映射,则返回失败
83 \n MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
84 \n MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;
85 * @param newAddr 在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,
86 \n 还必须指定MREMAP_MAYMOVE。
87 * @return void* 成功返回:重新映射后的虚拟内存地址
88 \n 失败返回:((void *)-1)。
89 */
90void *SysMremap(void *oldAddr, size_t oldLen, size_t newLen, int flags, void *newAddr)
91{
92 return (void *)LOS_DoMremap((vaddr_t)oldAddr, oldLen, newLen, flags, (vaddr_t)newAddr);
93}
94/**
95 * @brief 修改访问权限
96 * @param addr
97 * @return void*
98 */
99
100int SysMprotect(void *vaddr, size_t len, int prot)
101{
102 return LOS_DoMprotect((uintptr_t)vaddr, len, (unsigned long)prot);
103}
104
105/**
106 * @brief brk也是申请堆内存的一种方式,一般小于 128K 会使用它
107 * @param addr
108 * @return void*
109 */
110void *SysBrk(void *addr)
111{
112 return LOS_DoBrk(addr);
113}
114
115#ifdef LOSCFG_KERNEL_SHM
116/**
117 * @brief 得到一个共享内存标识符或创建一个共享内存对象
118 * @param key 建立新共享内存对象 标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上汇聚,需要提供一个外部命名方案。
119 \n 为此,每个IPC对象都与一个键(key)相关联,这个键作为该对象的外部名,无论何时创建IPC结构(通过msgget、semget、shmget创建),
120 \n 都应给IPC指定一个键, key_t由ftok创建,ftok当然在本工程里找不到,所以要写这么多.
121 * @param size 新建的共享内存大小,以字节为单位
122 * @param shmflg IPC_CREAT IPC_EXCL
123 \n IPC_CREAT: 在创建新的IPC时,如果key参数是IPC_PRIVATE或者和当前某种类型的IPC结构无关,则需要指明flag参数的IPC_CREAT标志位,
124 \n 则用来创建一个新的IPC结构。(如果IPC结构已存在,并且指定了IPC_CREAT,则IPC_CREAT什么都不做,函数也不出错)
125 \n IPC_EXCL: 此参数一般与IPC_CREAT配合使用来创建一个新的IPC结构。如果创建的IPC结构已存在函数就出错返回,
126 \n 返回EEXIST(这与open函数指定O_CREAT和O_EXCL标志原理相同)
127 * @return int
128 */
129int SysShmGet(key_t key, size_t size, int shmflg)
130{
131 int ret;
132
133 ret = ShmGet(key, size, shmflg);
134 if (ret < 0) {
135 return -get_errno();
136 }
137
138 return ret;
139}
140
141/**
142 * @brief @verbatim
143 连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
144 一旦创建/引用了一个共享存储段,那么进程就可调用shmat函数将其连接到它的地址空间中
145 如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值加1
146 @endverbatim
147 * @param shmid
148 * @param shmaddr
149 * @param shmflg
150 * @return void*
151 */
152void *SysShmAt(int shmid, const void *shmaddr, int shmflg)
153{
154 void *ret = NULL;
155
156 ret = ShmAt(shmid, shmaddr, shmflg);
157 if (ret == (void *)-1) {
158 return (void *)(intptr_t)-get_errno();
159 }
160
161 return ret;
162}
163
164/**
165 * @brief 完成对共享内存的控制
166 此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
167 * @param shmid 共享内存标识符
168 * @param cmd IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
169 \n IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
170 \n IPC_RMID:删除这片共享内存
171 * @param buf 共享内存管理结构体。
172 * @return int
173 */
174int SysShmCtl(int shmid, int cmd, struct shmid_ds *buf)
175{
176 int ret;
177
178 ret = ShmCtl(shmid, cmd, buf);
179 if (ret < 0) {
180 return -get_errno();
181 }
182
183 return ret;
184}
185
186/**
187 * @brief 与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存
188 * @param shmaddr 连接的共享内存的起始地址
189 * \n 本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程
190 * @return int 返回值 成功:0 出错:-1,错误原因存于error中
191 */
192int SysShmDt(const void *shmaddr)
193{
194 int ret;
195
196 ret = ShmDt(shmaddr);
197 if (ret < 0) {
198 return -get_errno();
199 }
200
201 return ret;
202}
203#endif
204
unsigned long vaddr_t
Definition: los_typedef.h:206
STATUS_T LOS_UnMMap(VADDR_T addr, size_t size)
解除映射关系
VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags, int fd, unsigned long pgoff)
INT32 ShmDt(const VOID *shmaddr)
当对共享存储的操作已经结束时,则调用shmdt与该存储段分离 如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值减1
Definition: shm.c:824
VADDR_T LOS_DoMremap(VADDR_T oldAddress, size_t oldSize, size_t newSize, int flags, VADDR_T newAddr)
重新映射虚拟内存地址。
INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf)
ShmCtl 此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
Definition: shm.c:703
VOID * LOS_DoBrk(VOID *addr)
VOID * ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg)
ShmAt 用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
Definition: shm.c:634
INT32 ShmGet(key_t key, size_t size, INT32 shmflg)
ShmGet 得到一个共享内存标识符或创建一个共享内存对象
Definition: shm.c:515
INT32 LOS_DoMprotect(VADDR_T vaddr, size_t len, unsigned long prot)
修改内存段的访问权限
Definition: shm.c:125
int GetAssociatedSystemFd(int procFd)
获取绑定的系统描述符
Definition: vfs_procfd.c:133
int SysShmGet(key_t key, size_t size, int shmflg)
得到一个共享内存标识符或创建一个共享内存对象
Definition: vm_syscall.c:129
int SysShmCtl(int shmid, int cmd, struct shmid_ds *buf)
完成对共享内存的控制 此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)
Definition: vm_syscall.c:174
void * SysMmap(void *addr, size_t size, int prot, int flags, int fd, size_t offset)
系统调用|申请虚拟内存(分配线性地址区间) 鸿蒙与Linux标准库的差异 http://weharmonyos.com/zh-cn/device-dev/kernel/%E4%B8%8ELinux%...
Definition: vm_syscall.c:58
void * SysMremap(void *oldAddr, size_t oldLen, size_t newLen, int flags, void *newAddr)
Definition: vm_syscall.c:90
void * SysShmAt(int shmid, const void *shmaddr, int shmflg)
Definition: vm_syscall.c:152
int SysMprotect(void *vaddr, size_t len, int prot)
修改访问权限
Definition: vm_syscall.c:100
int SysMunmap(void *addr, size_t size)
释放虚拟内存
Definition: vm_syscall.c:72
void * SysBrk(void *addr)
brk也是申请堆内存的一种方式,一般小于 128K 会使用它
Definition: vm_syscall.c:110
int SysShmDt(const void *shmaddr)
与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存
Definition: vm_syscall.c:192