android 共享内存 ioctl,(原创)匿名共享内存之文件描述符传递

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

dummy

0.1 目录树

Ashmem/

`-- jni

|-- Android.mk

|-- AshmemClient.cpp

|-- AshmemServer.cpp

`-- Common.h

0.2 源码

0.2.1 2.1 Common.h

#ifndef __Common__H_

#define __Common__H_

#define ASHMEM_SIZE1024

#define ASHEME_DEV"/dev/ashmem"

#define OPEN_FILE"/var/_cmsg_file"

#define CLIENT_SOCK_PATH"/var/_client_sock"

#define SERVER_SOCK_PATH"/var/_server_sock"

#define TEST_STRING"HelloWorld"

#endif

0.2.2 2.2 AshmemServer.cpp

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include"Common.h"

int main(int argc, char const* argv[])

{

int sockfd = -1, clientfd = -1, memfd = -1, testfd = -1;

int len = 0, ret = 0, err = -1, readn = 0;

char buf1[5];

char buf2[4];

char* mapaddr = 0;

struct sockaddr_un un;

struct cmsghdr* cmptr = 0;

struct cmsghdr* pcmsg = 0;

struct iovec iov[2];

struct msghdr msg;

sockfd = socket(PF_UNIX, SOCK_STREAM, 0);

if (sockfd < 0)

return err;

unlink(SERVER_SOCK_PATH);

memset(&un, 0, sizeof(un));

un.sun_family = AF_UNIX;

strcpy(un.sun_path, SERVER_SOCK_PATH);

len = offsetof(struct sockaddr_un, sun_path) + strlen(SERVER_SOCK_PATH);

ret = bind(sockfd, (struct sockaddr*)&un, len);

if (ret < 0) {

err = -2;

goto Err;

}

ret = listen(sockfd, 1);

if (ret < 0) {

err = -3;

goto Err;

}

len = sizeof(un);

memset(&un, 0, len);

clientfd = accept(sockfd, (struct sockaddr*)&un, &len);

if (clientfd < 0) {

err = -4;

goto Err;

}

printf("accept client fd =%dn", clientfd);

cmptr = (struct cmsghdr*)malloc(CMSG_SPACE(sizeof(int)));

if (!cmptr) {

err = -5;

goto Err;

}

iov[0].iov_base = buf1;

iov[0].iov_len = sizeof(buf1);

iov[1].iov_base = buf2;

iov[1].iov_len = sizeof(buf2);

msg.msg_iov = iov;

msg.msg_iovlen = 2;

msg.msg_name = 0;

msg.msg_namelen = 0;

msg.msg_control = cmptr;

msg.msg_controllen = CMSG_SPACE(sizeof(int));

readn = recvmsg(clientfd, &msg, 0);

if (readn <= 0) {

err = -6;

printf("Errno =%d%sn", errno, strerror(errno));

goto Err;

}

printf("buf1 =%snbuf2 =%sn", buf1, buf2);

pcmsg = CMSG_FIRSTHDR(&msg);

while (pcmsg) {

if ((pcmsg->cmsg_level == SOL_SOCKET)

&& (pcmsg->cmsg_type == SCM_RIGHTS)) {

if (pcmsg->cmsg_len == CMSG_LEN(sizeof(int))) {

memfd = *(int*)CMSG_DATA(pcmsg);

break;

}

}

pcmsg = CMSG_NXTHDR(&msg, pcmsg);

}

if (memfd > 0) {

mapaddr = (char*)mmap(0, ASHMEM_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, 0);

printf("get memfd =%dmapaddr =%pn", memfd, mapaddr);

}

memcpy(mapaddr, TEST_STRING, strlen(TEST_STRING));

sleep(5);

free(cmptr);

return 0;

Err:

printf("error =%dn", err);

close(sockfd);

return err;

}

0.2.3 2.3 AshmemClient.cpp

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include"Common.h"

int main(int argc, char const* argv[])

{

int sockfd = -1, memfd = -1, testfd = -1, err = -1;

int len =0, ret = 0, writen = 0;

char buf1[5] = {"file"};

char buf2[4] = {"map"};

char* mapaddr = 0;

char content[32] = { 0 };

struct sockaddr_un un;

struct cmsghdr* cmptr = 0;

struct cmsghdr* pcmsg = 0;

struct iovec iov[2];

struct msghdr msg;

sockfd = socket(PF_UNIX, SOCK_STREAM, 0);

if (sockfd < 0)

return err;

unlink(CLIENT_SOCK_PATH);

memset(&un, 0, sizeof(un));

un.sun_family = AF_UNIX;

strcpy(un.sun_path, CLIENT_SOCK_PATH);

len = offsetof(struct sockaddr_un, sun_path) + strlen(CLIENT_SOCK_PATH);

ret = bind(sockfd, (struct sockaddr*)&un, len);

if (ret < 0) {

err = -2;

goto Err;

}

memset(&un, 0, sizeof(un));

un.sun_family = AF_UNIX;

strcpy(un.sun_path, SERVER_SOCK_PATH);

len = offsetof(struct sockaddr_un, sun_path) + strlen(SERVER_SOCK_PATH);

ret = connect(sockfd, (struct sockaddr*)&un, len);

if (ret < 0) {

err = -3;

goto Err;

}

testfd = open(OPEN_FILE, O_CREAT|O_RDWR, 0777);

memfd = open(ASHEME_DEV, O_RDWR);

printf("open%sfd =%dn", ASHEME_DEV, memfd);

if (testfd < 0 || memfd < 0) {

err = -4;

goto Err;

}

ret = ioctl(memfd, ASHMEM_SET_SIZE, ASHMEM_SIZE);

if (ret < 0) {

err = -5;

goto Err;

}

mapaddr = (char*)mmap(0, ASHMEM_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, 0);

printf("mmap addr =%pn", mapaddr);

printf("sizeof(short) =%dn", sizeof(short));

printf("CMSG_ALIGN(sizeof(short)) =%dn", CMSG_ALIGN(sizeof(short)));

printf("CMSG_LEN(sizeof(short)) =%dn", CMSG_LEN(sizeof(short)));

printf("CMSG_SPACE(sizeof(short)) =%dn", CMSG_SPACE(sizeof(short)));

cmptr = (struct cmsghdr*)malloc(2*CMSG_SPACE(sizeof(int)));

if (!cmptr) {

err = -6;

goto Err;

}

printf("cmptr =%pn", cmptr);

iov[0].iov_base = buf1;

iov[0].iov_len = sizeof(buf1);

iov[1].iov_base = buf2;

iov[1].iov_len = sizeof(buf2);

msg.msg_iov = iov;

msg.msg_iovlen = 2;

msg.msg_name = 0;

msg.msg_namelen = 0;

msg.msg_control = cmptr;

msg.msg_controllen = 2*CMSG_SPACE(sizeof(int));

pcmsg = CMSG_FIRSTHDR(&msg);

printf("first pcmsg =%pn", pcmsg);

pcmsg->cmsg_level = SOL_SOCKET;

pcmsg->cmsg_type = SCM_RIGHTS;

pcmsg->cmsg_len = CMSG_LEN(sizeof(int));

*(int*)CMSG_DATA(pcmsg) = memfd;

//TODOsomething is wrong!

pcmsg = CMSG_NXTHDR(&msg, pcmsg);

printf("next pcmsg =%pn", pcmsg);

pcmsg->cmsg_level = SOL_SOCKET;

pcmsg->cmsg_type = SCM_RIGHTS;

pcmsg->cmsg_len = CMSG_LEN(sizeof(int));

*(int*)CMSG_DATA(pcmsg) = testfd;

writen = sendmsg(sockfd, &msg, 0);

printf("sendmsg write n =%d(sizeof(buf1) + sizeof(buf2) =%d)n", writen, sizeof(buf1) + sizeof(buf2));

sleep(2);

memcpy(content, mapaddr, strlen(TEST_STRING));

printf("content =%sn", content);

close(sockfd);

free(cmptr);

return 0;

Err:

printf("error :%dn", err);

close(sockfd);

return -1;

}

0.2.4 2.4 Android.mk

LOCAL_PATH:=$(callmy-dir)

JNI_RES_PATH:=/opt/android/jni

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS:=eng

LOCAL_MODULE:=AshmemServer

$(info"Build${LOCAL_MODULE})

LOCAL_SRC_FILES+=AshmemServer.cpp

LOCAL_C_INCLUDES+=${JNI_RES_PATH}/include${JNI_RES_PATH}/include/bionic/libc/kernel/common/

LOCAL_C_INCLUDES+=${JNI_RES_PATH}/include/bionic/libc/include/

LOCAL_CPPFLAGS+=-DDEBUG -DHAVE_ANDROID_OS -DHAVE_SYS_UIO_H

# 编译条件以及第三方库: -lxml2

LOCAL_LDFLAGS+=-L${JNI_RES_PATH}/libs -O2

# 系统库

LOCAL_LDLIBS+=-lcutils -lutils

# 动态库模块, 如果列出的库不存在会去编译 eg. libxxx

LOCAL_SHARED_LIBRARIES+=

# ALL_DEFAULT_INSTALLED_MODULES += $(LOCAL_MODULE)

# 目标输出类型

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS:=eng

LOCAL_MODULE:=AshmemClient

$(info"Build${LOCAL_MODULE})

LOCAL_SRC_FILES+=AshmemClient.cpp

LOCAL_C_INCLUDES+=${JNI_RES_PATH}/include${JNI_RES_PATH}/include/bionic/libc/kernel/common/

LOCAL_C_INCLUDES+=${JNI_RES_PATH}/include/bionic/libc/include/

LOCAL_CPPFLAGS+=-DDEBUG -DHAVE_ANDROID_OS -DHAVE_SYS_UIO_H

# 编译条件以及第三方库: -lxml2

LOCAL_LDFLAGS+=-L${JNI_RES_PATH}/libs -O2

# 系统库

LOCAL_LDLIBS+=-lcutils -lutils

# 动态库模块, 如果列出的库不存在会去编译 eg. libxxx

LOCAL_SHARED_LIBRARIES+=

# ALL_DEFAULT_INSTALLED_MODULES += $(LOCAL_MODULE)

include $(BUILD_EXECUTABLE)

0.3 3. 输出结果

0.3.1 3.1 /data/AshmemServeraccept client fd = 4

buf1 = file

buf2 = map

get memfd = 5 mapaddr = 0x76eb6000

0.3.2 3.2 /data/AshmemClientopen /dev/ashmem fd = 5

mmap addr = 0x76e7a000

sizeof(short) = 2

CMSG_ALIGN(sizeof(short)) = 4

CMSG_LEN(sizeof(short)) = 14

CMSG_SPACE(sizeof(short)) = 16

cmptr = 0xc9e0a8

first pcmsg = 0xc9e0a8

next pcmsg = 0xc9e0b8

sendmsg write n = 9 (sizeof(buf1) + sizeof(buf2) = 9)

content = HelloWorld

0.4 4. 总结Android匿名共享内存多个进程实现共享, 那么每个进程都要拿到这个/dev/ashmem打开的文件描述符

通过msghdr这个结构体加上sendmsg和recvmsg实现文件描述符的进程间传递

之所以要进程间传递文件描述符,是因为"匿名"二字, 如果通讯的每个进程都打开/dev/ashmem文件是实现不了的.

sendmsg是怎样把文件描述符传递的, 是不是有点像dup或dup2, 复制现存的文件描述符, 使他们指向同一个file结构体(本进程内)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值