Linux高级进程间通信 共享存储

shmcopy:
将标准输入复制到标准输出上,shmcopy运行后将生成两个进程:一个读进程,一个写进程,它们共享
两个作为共享存储段实现的缓冲区。当读进程读取数据放入第一个缓冲区时,写进程将输出第二个缓冲区
的内容,反之亦然。由于读和写是同步进程的,因此数据的输入输出总和将会增加,可以快速处理数据。
为促使两个进程协作,可以使用两个二进制的信号量进行进程同步。

 

share_ex.h:

 

/* header file for shared memory example */

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>

#define SHMKEY1 (key_t)0x10   /*share memory key 1*/
#define SHMKEY2 (key_t)0x15   /*share memory key 2*/
#define SEMKEY  (key_t)0x20   /*semaphore  key */
#define debug   0        //no debug  关闭调试信息
/*buffer size for reads and writes */
#define SIZ  5*BUFSIZ   /*BUFSIZ define in <stdiio.h>,it return 
                                                     the size of system block */
/*will hold data and read count */
struct databuf
{
    int d_nread;
    char d_buf[SIZ];
};

typedef union _semun//通过别名可以像semun mysem;一样定义联合体
{
    int val;
    struct semid_ds *buf;
    ushort *array;
}semun;


 

init.c:

/* initilization routines*/
#include "share_ex.h"
#include<stdlib.h>

#define IFLAGS   (IPC_CREAT|IPC_EXCL)
#define  ERR   ((struct databuf*)-1)
static int shmid1,shmid2,semid;

void getseg(struct databuf **p1,struct databuf **p2)
{
    /*create shared memory segment */
    if((shmid1=shmget(SHMKEY1,sizeof(struct databuf),0600|IFLAGS))==-1)
    {
        fatal("shmget");
    }

    if((shmid2=shmget(SHMKEY2,sizeof(struct databuf),0600|IFLAGS))==-1)
    {
        fatal("shmget");
    }

    /*attach shared memory segments */
    if((*p1=(struct databuf *)shmat(shmid1,NULL,0))==ERR)
    {
        fatal("shmat");
    }
    if((*p2=(struct databuf *)shmat(shmid2,NULL,0))==ERR)
    {
        fatal("shmat");
    }
}

int getsem(void)     //get semaphore set 
{
    semun x;
    x.val=0;

    /* create two semaphore set */
    if((semid=semget(SEMKEY,2,0600|IFLAGS))==-1)//2 sem?
    {
        fatal("semget");
    }
  
    /* set initial values */
    if(semctl(semid,0,SETVAL,x)==-1)
    {
        fatal("semctl");
    }

    if(semctl(semid,1,SETVAL,x)==-1)
    {
        fatal("semctl");
    }

    return (semid);

}

/* remove shared memory identifiers +sem set id*/
void remobj(void)
{
    if(shmctl(shmid1,IPC_RMID,NULL)==-1)//share memory remove
    {
        fatal("shmctl");
    }
    if(shmctl(shmid2,IPC_RMID,NULL)==-1)//share memory remove
    {
        fatal("shmctl");
    }
    if(semctl(semid,2,IPC_RMID,NULL)==-1) //semaphore remove 。semctl有四个参数的
    {
        fatal("semctl");
    }
}

int fatal(char *err)
{
    perror(err);
    exit (1);
}


 

reader.c:

/* reader-----handle reading of file--from 0 standard input */

#include "share_ex.h"

/* these define p() and v() for two semaphores */
struct sembuf p1={0,-1,0},p2={1,-1,0};//p means wait
struct sembuf v1={0, 1,0},v2={1, 1,0};//v means signal

//reader 和writer之间通过p,v操作实现同步,程序执行的顺序是ABCDEFGH.由此实现了先读后写的顺序
void reader(int semid,struct databuf *buf1,struct databuf *buf2)
{
    if(debug)
    {
        printf("reader call succeeded\n");
    }
    for(;;)
    {
        /*read into bufer buf1 */
        buf1->d_nread=read(0,buf1->d_buf,SIZ);//进程先读


        /*synchronization point */
        semop(semid,&v1,1);//A
        semop(semid,&p2,1);//D


        /* test here to avoid writer sleeping */
        if(buf1->d_nread<=0)//no data to read
        {
            if(debug)
                printf("reader exit  because buf1->d_nread<=0\n");
            return ;
        }
   
        /* read into bufer buf2 */
        buf2->d_nread=read(0,buf2->d_buf,SIZ);

        semop(semid,&v1,1);//E
        semop(semid,&p2,1);//H

        if(buf2->d_nread<=0)
        {
            if(debug)
            {
                printf("reader exit because buf->d_nread<=0\n");
            }
            return;
        }
    }
}


writer.c:

/* writer---handle writing */

#include "share_ex.h"

extern struct sembuf p1,p2;//define in reader.c
extern struct sembuf v1,v2;//define in reader.c

void writer(int semid,struct databuf *buf1,struct databuf *buf2)
{
    if(debug)
    {
        printf("writer call succeeded\n");
    }
    for(;;)
    {
        semop(semid,&p1,1);//B等待reader读完再写
        semop(semid,&v2,1);//C

        if(buf1->d_nread<=0)
        {
            if(debug)
            {
                printf("writer exit because buf1->d_nread<=0\n");
            }
            return;
        }

        write(1,buf1->d_buf,buf1->d_nread);

        semop(semid,&p1,1);//F
        semop(semid,&v2,1);//G

        if(buf2->d_nread<=0)
        {
            if(debug)
            {
                printf("writer exit because buf2->d_nread<=0\n");
            }
            return;
        }
        write(1,buf2->d_buf,buf2->d_nread);

        
    }
}


shmcopy.c:

 

/* shmcopy---main function.*/
#include<stdlib.h>
#include "share_ex.h"

int main(void)
{
    int semid;
    pid_t pid;
    struct databuf *buf1,*buf2;

    /*initilization semaphore set */
    semid=getsem();

    /* create and attach shared memory segments */
    getseg(&buf1,&buf2);

    switch(pid=fork())
    {
        case -1:
            fatal("fork");
        case 0://child子进程写
            writer(semid,buf1,buf2);
            remobj();
            break;
        default:  //parent父进程读
            reader(semid,buf1,buf2);
            break;
    }

    exit (0);
}

运行结果:

jiang@jiang-linux:~/unixprog/2011325$ gcc init.c reader.c writer.c shmcopy.c -o shmcopy.o;./shmcopy.o<reader.c>test;//实现将reader.c 复制到test中。




 

ipcs和ipcrm共享内存相关命令用法


命令名称:ipcs

使用权限:所有使用者

使用方式:

ipcs [-m|-q|-s]
-m       输出有关共享内存(shared memory)的信息
-q       输出有关信息队列(message queue)的信息
-s       输出有关“遮断器”(semaphore)的信息

 

命令名称:ipcrm

使用权限 :所有使用者

使用方式 

       ipcrm [ -M key | -m id | -Q key | -q id | -S key | -s id ] ...

说明 :删除消息队列、共享内存、信号灯

参数 

-M   以 shmkey 删除共享内存

-m   以 shmid 删除共享内存

-Q   以 msgkey 删除消息队列

-q    以 msgid 删除消息队列

-S    以 semkey 删除信号灯

-s    以 semid 删除信号灯

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值