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 删除信号灯