• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "shared_memory.h"
17 
18 #include <cerrno>
19 #include <cstdlib>
20 #include <cstring>
21 #include <sys/shm.h>
22 #include "hilog_wrapper.h"
23 #include "securec.h"
24 
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 constexpr int SHM_KEY_START = 400000; // chosen randomly
29 constexpr int SHM_KEY_END   = 500000; // chosen randomly
30 constexpr unsigned int SHM_READ_WRITE_PERMISSIONS = 0666U;
31 
32 #ifndef EOK
33 #define EOK (0)
34 #endif
35 }
36 
ReleaseShmId(int shmId)37 void SharedMemory::ReleaseShmId(int shmId)
38 {
39     if (shmId == -1) {
40         return;
41     }
42     if (shmctl(shmId, IPC_RMID, nullptr) == -1) {
43         HILOG_ERROR("shmctl IPC_RMID failed: %{public}d.", errno);
44         return;
45     }
46 }
47 
PushSharedMemory(const void * data,int size)48 int SharedMemory::PushSharedMemory(const void *data, int size)
49 {
50     // internal call, no need to check null.
51     static int shmKey = SHM_KEY_START;
52     int shmId;
53     while ((shmId = shmget(shmKey, size, SHM_READ_WRITE_PERMISSIONS | IPC_CREAT | IPC_EXCL)) < 0) {
54         if (errno == EEXIST) {
55             ++shmKey;
56             if (shmKey >= SHM_KEY_END) {
57                 shmKey = SHM_KEY_START;
58             }
59             continue;
60         }
61         HILOG_ERROR("shmget failed: %{public}d.", errno);
62         return -1;
63     }
64     HILOG_INFO("shmget succeed, shmKey = %{public}d, shmId = %{public}d.", shmKey, shmId);
65 
66     void *shared = shmat(shmId, nullptr, 0);
67     if (shared == reinterpret_cast<void *>(-1)) {
68         ReleaseShmId(shmId);
69         HILOG_ERROR("shmat failed: %{public}d.", errno);
70         return -1;
71     }
72 
73     int retCode;
74     if ((retCode = memcpy_s(shared, size, data, size)) != EOK) {
75         shmdt(shared);
76         ReleaseShmId(shmId);
77         HILOG_ERROR("memcpy_s failed: %{public}d.", retCode);
78         return -1;
79     }
80 
81     if (shmdt(shared) == -1) {
82         ReleaseShmId(shmId);
83         HILOG_ERROR("shmdt failed: %{public}d.", errno);
84         return -1;
85     }
86 
87     return shmKey;
88 }
89 
PopSharedMemory(int shmKey,int size)90 void* SharedMemory::PopSharedMemory(int shmKey, int size)
91 {
92     if (size <= 0) {
93         HILOG_ERROR("size is invalid: %{public}d.", size);
94         return nullptr;
95     }
96 
97     int shmId = shmget(shmKey, 0, 0 | SHM_READ_WRITE_PERMISSIONS);
98     if (shmId == -1) {
99         HILOG_ERROR("shmId is invalid: %{public}d, %{public}d.", shmId, errno);
100         return nullptr;
101     }
102 
103     void *shared = shmat(shmId, nullptr, 0);
104     if (shared == reinterpret_cast<void *>(-1)) {
105         HILOG_ERROR("shmat failed %{public}d.", errno);
106         ReleaseShmId(shmId);
107         return nullptr;
108     }
109 
110     void *data = reinterpret_cast<void *>(malloc(size));
111     if (data == nullptr) {
112         HILOG_ERROR("malloc failed %{public}d.", errno);
113         return nullptr;
114     }
115     int retCode = memcpy_s(data, size, shared, size);
116     if (retCode != EOK) {
117         shmdt(shared);
118         ReleaseShmId(shmId);
119         HILOG_ERROR("Failed to memory copy, retCode[%{public}d].", retCode);
120         free(data);
121         return nullptr;
122     }
123 
124     if (shmdt(shared) == -1) {
125         ReleaseShmId(shmId);
126         HILOG_ERROR("shmdt failed: %{public}d.", errno);
127         free(data);
128         return nullptr;
129     }
130 
131     ReleaseShmId(shmId);
132 
133     return data;
134 }
135 
136 }  // namespace AAFwk
137 }  // namespace OHOS