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