Chinaunix首页 | 论坛 | 博客
  • 博客访问: 333044
  • 博文数量: 102
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 1146
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-21 22:33
文章分类

全部博文(102)

文章存档

2011年(8)

2010年(94)

我的朋友

分类: LINUX

2010-01-23 20:47:39

shmem/ashmem/mmap等一些知识

story:
1.*提到了在sensors层建立share memory方便进程交互数据.也可以用mmap
2. * said Android discard shmem with ashmem now.

let me hack some bits.

1. 文档
Documentation/vm/hugetlbpage.txt
虽然是讲huge table 应用的,但里面2 example不错.

"
Users can use the huge page support in Linux kernel by either using the mmap
system call or standard SYSv shared memory system calls (shmget, shmat).
"

code:
*******************************************************************

/*
 * Example of using hugepage memory in a user application using Sys V shared
 * memory system calls.  In this example the app is requesting 256MB of
 * memory that is backed by huge pages.  The application uses the flag
 * SHM_HUGETLB in the shmget system call to inform the kernel that it is
 * requesting hugepages.
 *
 * For the ia64 architecture, the Linux kernel reserves Region number 4 for
 * hugepages.  That means the addresses starting with 0x800000... will need
 * to be specified.  Specifying a fixed address is not required on ppc64,
 * i386 or x86_64.
 *
 * Note: The default shared memory limit is quite low on many kernels,
 * you may need to increase it via:
 *
 * echo 268435456 > /proc/sys/kernel/shmmax
 *
 * This will increase the maximum size per shared memory segment to 256MB.
 * The other limit that you will hit eventually is shmall which is the
 * total amount of shared memory in pages. To set it to 16GB on a system
 * with a 4kB pagesize do:
 *
 * echo 4194304 > /proc/sys/kernel/shmall
 */
#include
#include
#include
#include
#include
#include

#ifndef SHM_HUGETLB
#define SHM_HUGETLB 04000
#endif

#define LENGTH (256UL*1024*1024)

#define dprintf(x)  printf(x)

/* Only ia64 requires this */
#ifdef __ia64__
#define ADDR (void *)(0x8000000000000000UL)
#define SHMAT_FLAGS (SHM_RND)
#else
#define ADDR (void *)(0x0UL)
#define SHMAT_FLAGS (0)
#endif

int main(void)
{
int shmid;
unsigned long i;
char *shmaddr;

if ((shmid = shmget(2, LENGTH,
    SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
perror("shmget");
exit(1);
}
printf("shmid: 0x%x\n", shmid);

shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
if (shmaddr == (char *)-1) {
perror("Shared memory attach failure");
shmctl(shmid, IPC_RMID, NULL);
exit(2);
}
printf("shmaddr: %p\n", shmaddr);

dprintf("Starting the writes:\n");
for (i = 0; i < LENGTH; i++) {
shmaddr[i] = (char)(i);
if (!(i % (1024 * 1024)))
dprintf(".");
}
dprintf("\n");

dprintf("Starting the Check...");
for (i = 0; i < LENGTH; i++)
if (shmaddr[i] != (char)i)
printf("\nIndex %lu mismatched\n", i);
dprintf("Done.\n");

if (shmdt((const void *)shmaddr) != 0) {
perror("Detach failure");
shmctl(shmid, IPC_RMID, NULL);
exit(3);
}

shmctl(shmid, IPC_RMID, NULL);

return 0;
}

*******************************************************************

/*
 * Example of using hugepage memory in a user application using the mmap
 * system call.  Before running this application, make sure that the
 * administrator has mounted the hugetlbfs filesystem (on some directory
 * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
 * example, the app is requesting memory of size 256MB that is backed by
 * huge pages.
 *
 * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
 * That means the addresses starting with 0x800000... will need to be
 * specified.  Specifying a fixed address is not required on ppc64, i386
 * or x86_64.
 */
#include
#include
#include
#include
#include

#define FILE_NAME "/mnt/hugepagefile"
#define LENGTH (256UL*1024*1024)
#define PROTECTION (PROT_READ | PROT_WRITE)

/* Only ia64 requires this */
#ifdef __ia64__
#define ADDR (void *)(0x8000000000000000UL)
#define FLAGS (MAP_SHARED | MAP_FIXED)
#else
#define ADDR (void *)(0x0UL)
#define FLAGS (MAP_SHARED)
#endif

void check_bytes(char *addr)
{
printf("First hex is %x\n", *((unsigned int *)addr));
}

void write_bytes(char *addr)
{
unsigned long i;

for (i = 0; i < LENGTH; i++)
*(addr + i) = (char)i;
}

void read_bytes(char *addr)
{
unsigned long i;

check_bytes(addr);
for (i = 0; i < LENGTH; i++)
if (*(addr + i) != (char)i) {
printf("Mismatch at %lu\n", i);
break;
}
}

int main(void)
{
void *addr;
int fd;

fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
if (fd < 0) {
perror("Open failed");
exit(1);
}

addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
unlink(FILE_NAME);
exit(1);
}

printf("Returned address is %p\n", addr);
check_bytes(addr);
write_bytes(addr);
read_bytes(addr);

munmap(addr, LENGTH);
close(fd);
unlink(FILE_NAME);

return 0;
}

2. 看shmget等几个 systemcall

shmget(2) - Linux man page

使用方式

shmget() returns the identifier of the shared memory segment associated with the value of the argumentkey. A new shared memory segment, with size equal to the value of size rounded up to a multiple of PAGE_SIZE, is created if key has the valueIPC_PRIVATE or key isn'tIPC_PRIVATE, no shared memory segment corresponding to key exists, and IPC_CREAT is specified inshmflg.

要跟一个进程绑定在一起来

shmat(2) - Linux man page

shmat() attaches the shared memory segment identified byshmid to the address space of the calling process. The attaching address is specified by shmaddr with one of the following criteria:


shmdt() detaches the shared memory segment located at the address specified by shmaddr from the address space of the calling process. The to-be-detached segment must be currently attached with shmaddr equal to the value returned by the attaching shmat() call.

Shmctl(2) - Linux man page

shmctl() performs the control operation specified by cmd on the shared memory segment whose identifier is given in shmid.

IPC_RMID

Mark the segment to be destroyed. The segment will only actually be destroyed after the last process detaches it (i.e., when the shm_nattch member of the associated structure shmid_ds is zero). The caller must be the owner or creator, or be privileged. If a segment has been marked for destruction, then the (non-standard) SHM_DEST flag of the shm_perm.mode field in the associated data structure retrieved by IPC_STAT will be set.


Summary:

1. shmget申请memory返回一个 share memory id,不 进程可以申请 绑定此id代表的进程地址空间.这个地址空间可以在不同的process之间共享的. 要注意其destroy的方式,权限.
2. mmap要对一个fd 文件指针操作,呈现给进程的也是一段vma,操作结果最终与文件进行映射. 

logo.gif   这个网站帮忙了.



//ashmem_area - android shared memory area是android共享内容存的一种方式
//打开ashmem设备,申请一段size大小的kernel空间内存,不去释放,以便供所有用户空间进程共享.
//内核驱动位于linux/mm/ashmem.c文件[luther.gliethttp].

ashmem.c里面,在初始化的时候,做了3个事情:
1.申请area/range  ashmem cache object.
2. register ashmem misc device
3. register shrinker for shrink pages in vmscan.c

misc file_operations has mmap field,
static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
this function will bind file and vma.And invoke 
void shmem_set_file(struct vm_area_struct *vma, struct file *file)
 to set vma's vm_file and vm_ops.

所以在android里面,不同进程share memory可以通过open /dev/ashmem结点来进行操作

至于其中的ashmem处理机制呢,以及fileoperations里的mmap方式,pin/unpin操作,等具体接触问题时再研究.

阅读(2090) | 评论(1) | 转发(0) |
0

上一篇:Dalvik虚拟机简介

下一篇:Mmap笔记

给主人留下些什么吧!~~

chinaunix网友2010-07-12 20:11:54

我K...原来是自己人阿。。。早知道打电话问你了