Linux环境下进程之间通过内存共享实现通信的方式有很多种。
1. shm_XXX 这种函数,可以实现在不同进程之间(尤其是非父母进程之间)进行内存共享
write.c文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
/*
int shm_open(const char *name, int oflag, mode_t mode);
//创建或打开一个共享内存,成功返回一个整数的文件描述符,错误返回-1。
1.name:共享内存区的名字;
2.标志位;open的标志一样
3.权限位
int shm_unlink(const char *name);
编译时要加库文件-lrt
*/
#define SHMNAME "shm_ram"
#define OPEN_FLAG O_RDWR|O_CREAT
#define OPEN_MODE 00777
#define FILE_SIZE 4096*4
int main(void)
{
int ret = -1;
int fd = -1;
void* add_w = NULL;
//创建或者打开一个共享内存
fd = shm_open(SHMNAME, OPEN_FLAG, OPEN_MODE);
if(-1 == (ret = fd))
{
perror("shm failed: ");
goto _OUT;
}
//调整确定文件共享内存的空间
ret = ftruncate(fd, FILE_SIZE);
if(-1 == ret)
{
perror("ftruncate faile: ");
goto _OUT;
}
//映射目标文件的存储区
add_w = mmap(NULL, FILE_SIZE, PROT_WRITE, MAP_SHARED, fd, SEEK_SET);
if(NULL == add_w)
{
perror("mmap src failed: ");
goto _OUT;
}
//memcpy 内存共享 写入内容
memcpy(add_w, "howaylee", sizeof("howaylee"));
//取消映射
ret = munmap(add_w, FILE_SIZE);
if(-1 == ret)
{
perror("munmap add_w faile: ");
goto _OUT;
}
//删除内存共享
/*shm_unlink(SHMNAME);
if(-1 == ret)
{
perror("shm_unlink faile: ");
goto _OUT;
}*/
_OUT:
return ret;
}
read.c文件
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
/*
int shm_open(const char *name, int oflag, mode_t mode);
//创建或打开一个共享内存,成功返回一个整数的文件描述符,错误返回-1。
1.name:共享内存区的名字;
2.标志位;open的标志一样
3.权限位
int shm_unlink(const char *name);
编译时要加库文件-lrt
*/
#define SHMNAME "shm_ram"
#define OPEN_FLAG O_RDWR|O_CREAT
#define OPEN_MODE 00777
#define FILE_SIZE 4096*4
int main(void)
{
int ret = -1;
int fd = -1;
char buf[4096] = {0};
void* add_r = NULL;
//创建或者打开一个共享内存
fd = shm_open(SHMNAME, OPEN_FLAG, OPEN_MODE);
if(-1 == (ret = fd))
{
perror("shm failed: ");
goto _OUT;
}
//调整确定文件共享内存的空间
ret = ftruncate(fd, FILE_SIZE);
if(-1 == ret)
{
perror("ftruncate faile: ");
goto _OUT;
}
//映射目标文件的存储区
add_r = mmap(NULL, FILE_SIZE, PROT_READ, MAP_SHARED, fd, SEEK_SET);
if(NULL == add_r)
{
perror("mmap add_r failed: ");
goto _OUT;
}
//memcpy 内存共享 写入内容
memcpy(buf, add_r, sizeof(buf));
printf("buf = %s\n", buf);
//取消映射
ret = munmap(add_r, FILE_SIZE);
if(-1 == ret)
{
perror("munmap add_r faile: ");
goto _OUT;
}
/*
//删除内存共享
shm_unlink(SHMNAME);
if(-1 == ret)
{
perror("shm_unlink faile: ");
goto _OUT;
}
*/
_OUT:
return ret;
}
编译的时候gcc加上-lrt,分别编译出write,read。
./write之后./read会输出 "buf = howaylee"
2. shmget等函数也可以
client.c文件
/* 编译命令:gcc -o client client.c -g*/
#include<sys/sem.h>
#include<time.h>
#include<sys/ipc.h>
#define SEGSIZE 1024
#define READTIME 1
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
/* 打印程序的执行时间函数 */
void out_time(void)
{
static long start = 0;
time_t tm;
if (start == 0)
{
tm = time(NULL);
start = (long)tm;
printf("now start \n");
}
printf("second: %d\n", (long)(time(NULL)) - start);
}
/* 创建信号量 */
int new_sem(key_t key)
{
union semun sem;
int semid;
sem.val = 0;
semid = semget(key, 0, 0);
if (-1 == semid)
{
printf("create semaphore error\n");
exit(-1);
}
return semid;
}
/* 信号量等待函数,等待信号量的值变为0 */
void wait_v(int semid)
{
struct sembuf sops = {0,
0,
0
};
semop(semid, &sops, 1);
}
int main(int argc, char **argv)
{
key_t key;
int shmid, semid;
char *shm;
char msg[100];
char i;
key = ftok("/", 0);
shmid = shmget(key, SEGSIZE, 0);
if (shmid == -1)
{
printf("create shared memory error\n");
return -1;
}
semid = new_sem(key);
for (i = 0;i < 3;i ++)
{
sleep(2);
wait_v(semid);
printf("Message geted is: %s \n",shm + 1);
out_time();
}
shmdt(shm);
return 0;
}
server.c文件
#include<sys/types.h>
#include<sys/sem.h>
#include<sys/ipc.h>
#include<stdio.h>
#include<unistd.h>
union semum
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
#define SEGSIZE 1024
#define READTIME 1
/* 创建信号量 */
int sem_creat(key_t key)
{
union semun sem;
int semid;
sem.val = 0;
semid = semget(key, 1, IPC_CREAT | 0666);
if (semid == -1)
{
printf("Create semaphore error\n");
exit(-1);
}
semctl(semid, 0, SETVAL, sem);
return semid;
}
/* 删除信号量*/
int del_sem(int semid)
{
union semun sem;
sem.val = 0;
semctl(semid, 0, IPC_RMID, sem);
}
/* 信号量的P操作,使得信号量的值加1 */
int p(int semid)
{
struct sembuf sops = {0,
+1,
IPC_NOWAIT
};
return (semop(semid, &sops, 1));
}
/* 信号量的v操作,使得信号量的值减1 */
int v(int semid)
{
struct sembuf sops = {0,
-1,
IPC_NOWAIT
};
return (semop(semid, &sops, 1));
}
/* server主程序 */
int main(int argc, char **argv)
{
key_t key;
int shmid, semid;
char *shm;
char msg[7] = "-data-";
char i;
struct semid_ds buf;
key = ftok("/", 0);
shmid = shmget(key, SEGSIZE, IPC_CREAT|0604);
if shmid == -1)
{
printf(" create shared memory error\n");
return -1;
}
shm = (char *)shmat(shmid, 0, 0);
if (-1 == (int)shm)
{
printf(" attach shared memory error\n");
return -1;
}
semid = sem_creat(key);
for (i = 0; i <= 3; i++)
{
sleep(1);
p(semid);
sleep(READTIME);
msg[5] = '0' + i;
memcpy(shm,msg,sizeof(msg));
sleep(58);
v(semid);
}
shmdt(shm);
shmctl(shmid,IPC_RMID,&buf);
del_sem(semid);
return 0;
}
3. android通过ion内存来实现父进程和子进程之间的内存共享(不知道非父子进程之间怎么用ion内存)
4. 通过mmap实现()