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實現()