共享内存

进程间通过共享内存交换信息

例1:

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>

#define ERROR(flag,msg)            \
if(flag)                        \
{                                \
    printf("%d: ",__LINE__);    \
    fflush(stdout);                \
    perror(msg);                \
    exit(errno);                \
}

#define PATH_NAME "/home/"
#define PROJ_ID 100
#define SHMBUF_SIZE 1000

static int shmid;
static char *shmaddr;
static int semid;


void create_shm()
{
    key_t key = ftok(PATH_NAME,PROJ_ID);
    ERROR(key == -1,"ftok()");

    shmid = shmget(key,SHMBUF_SIZE,IPC_CREAT | 0600);
    ERROR(shmid == -1,"shmget()");

    shmaddr = shmat(shmid,NULL,0);
    ERROR(shmaddr == (void *)-1,"shmat()");
}

void delete_shm()
{
    int ret = shmdt(shmaddr);
    ERROR(ret == -1,"shmdt");


    ret = shmctl(shmid,IPC_RMID,NULL);
}

void create_sem()
{
    key_t key = ftok(PATH_NAME,PROJ_ID);
    ERROR(key == -1,"ftok()");

    semid = semget(key,2,IPC_CREAT | 0600);
    ERROR(semid == -1,"semget()");

#if 0
    int ret = semctl(semid,0,SETVAL,1);
    ERROR(ret == -1,"semctl()");
#endif
}

void delete_sem()
{
    semctl(semid,0,IPC_RMID);
}

void lock()
{
    struct sembuf sops;

    sops.sem_num = 0;
    sops.sem_op = -1;
    sops.sem_flg = 0;

    semop(semid,&sops,1);
}

void unlock()
{
    struct sembuf sops;

    sops.sem_num = 0;
    sops.sem_op = 1;
    sops.sem_flg = 0;

    semop(semid,&sops,1);
}

void handler(int signum)
{
    delete_sem();
    delete_shm();
    exit(0);
}

int main(int argc, char *argv[])
{
    signal(SIGINT,handler);

    create_shm();
    create_sem();

    lock();
    bzero(shmaddr,SHMBUF_SIZE);
    memcpy(shmaddr,argv[2],SHMBUF_SIZE);
    unlock();

    while(1)
    {
        lock();

        puts(shmaddr);
        bzero(shmaddr,SHMBUF_SIZE);
        memcpy(shmaddr,argv[2],SHMBUF_SIZE);
        sleep(atoi(argv[1]));

        unlock();
    }

    delete_sem();
    delete_shm();
    return 0;
}

server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>

#define ERROR(flag,msg)            \
if(flag)                        \
{                                \
    printf("%d: ",__LINE__);    \
    fflush(stdout);                \
    perror(msg);                \
    exit(errno);                \
}

#define PATH_NAME "/home/"
#define PROJ_ID 100
#define SHMBUF_SIZE 1000

static int shmid;
static char *shmaddr;
static int semid;


void create_shm()
{
    key_t key = ftok(PATH_NAME,PROJ_ID);
    ERROR(key == -1,"ftok()");

    shmid = shmget(key,SHMBUF_SIZE,IPC_CREAT | 0600);
    ERROR(shmid == -1,"shmget()");

    shmaddr = shmat(shmid,NULL,0);
    ERROR(shmaddr == (void *)-1,"shmat()");
}

void delete_shm()
{
    int ret = shmdt(shmaddr);
    ERROR(ret == -1,"shmdt");


    ret = shmctl(shmid,IPC_RMID,NULL);
}

void create_sem()
{
    key_t key = ftok(PATH_NAME,PROJ_ID);
    ERROR(key == -1,"ftok()");

    semid = semget(key,2,IPC_CREAT | 0600);
    ERROR(semid == -1,"semget()");

    int ret = semctl(semid,0,SETVAL,1);
    ERROR(ret == -1,"semctl()");

}

void delete_sem()
{
    semctl(semid,0,IPC_RMID);
}

void lock()
{
    struct sembuf sops;

    sops.sem_num = 0;
    sops.sem_op = -1;
    sops.sem_flg = SEM_UNDO;

    semop(semid,&sops,1);
}

void unlock()
{
    struct sembuf sops;

    sops.sem_num = 0;
    sops.sem_op = 1;
    sops.sem_flg = SEM_UNDO;

    semop(semid,&sops,1);
}

void handler(int signum)
{
    delete_sem();
    delete_shm();
    exit(0);
}

int main(int argc, char *argv[])
{
    signal(SIGINT,handler);

    create_shm();
    create_sem();

    lock();
    bzero(shmaddr,SHMBUF_SIZE);
    memcpy(shmaddr,argv[2],SHMBUF_SIZE);
    unlock();
    while(1)
    {
        lock();

        puts(shmaddr);
        bzero(shmaddr,SHMBUF_SIZE);
        memcpy(shmaddr,argv[2],SHMBUF_SIZE);
        sleep(atoi(argv[1]));

        unlock();
    }

    delete_sem();
    delete_shm();
    return 0;
}

编译/链接执行后,结果如下:

server和client同时执行后, 每5秒打印一次共享内存中取出的数据. server打印出的都是client写入到共享内存的数据c5, client打印的都是server写入到共享内存的数据s1. 

对共享内存读写时的同步, 通过封装成lock()/unlock()信号量操作函数实现.

client先退出后, server每1秒打印共享内存中的数据. 由于没有了client端写入的数据, 打印的都是自己写入的数据s1.

posted @ 2015-12-30 22:28  zhanglong71  阅读(177)  评论(0编辑  收藏  举报