一、安卓开启Sys V IPC
1.1 配置kernel
为了在安卓下使用shm
,我们需要开启Sys V IPC功能,首先我们需要开启kernel的general -> Sys V IPC
。
1.2 修改domain.te
之后我们将./system/sepolicy/public/domain.te
中的neverallow * *:{ shm sem msg msgq } *;
修改为neverallow * *:{ sem msg msgq } *;
。这里根据需要移除对应的IPC选型,在编译时我遇到了报错,提示还需要保持./system/sepolicy/prebuilts/api/30/public/domain.te
和上述文件一致。
1.3 修改check_vintf.cpp
安卓编译的时候还会有一个检查,以确保CONFIG_SYS_V_IPC设置为n,为了规避这项检查,我们需要修改./system/libvintf/check_vintf.cpp
中的代码:
if (compat.ok()) {
std::cout << "COMPATIBLE" << std::endl;
return EX_OK;
}
if (compat.error().code() == 0) {
LOG(ERROR) << "files are incompatible: " << compat.error();
std::cout << "INCOMPATIBLE" << std::endl;
// return EX_DATAERR;
return EX_OK;
}
LOG(ERROR) << strerror(compat.error().code()) << ": " << compat.error();
return EX_SOFTWARE;
这里我们将return EX_DATAERR;
修改为return EX_OK;
,但是在修改的时候需要确保你的系统没有其他错误。建议先正常编译后,再开启Sys V IPC功能。
二、使用共享内存通信
2.1 发送进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
int shmid;
char *shmaddr;
char message[] = "hello world";
key_t key1 = ftok("/data/local/tmp/key/test_key", 1);
// 创建共享内存段
shmid = shmget(key1, sizeof(message), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
// 将共享内存连接到当前进程的地址空间
shmaddr = (char *)shmat(shmid, NULL, 0);
if (shmaddr == (char *)(-1)) {
perror("shmat");
exit(1);
}
// 将数据写入共享内存
strcpy(shmaddr, message);
printf("Message '%s' written to shared memory\n", message);
// 分离共享内存
shmdt(shmaddr);
return 0;
}
2.2 接收进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main() {
int shmid;
char *shmaddr;
key_t key1 = ftok("/data/local/tmp/key/test_key", 1);
// 获取共享内存段 12 is sizeof("hello world")
shmid = shmget(key1, 12, 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
// 连接到共享内存段
shmaddr = (char *)shmat(shmid, NULL, 0);
if (shmaddr == (char *)(-1)) {
perror("shmat");
exit(1);
}
// 从共享内存读取数据并打印
printf("Read from shared memory: %s\n", shmaddr);
// 分离共享内存
shmdt(shmaddr);
// 删除共享内存段(在实际应用中,可能需要谨慎处理删除操作)
shmctl(shmid, IPC_RMID, NULL);
return 0;
}