Linux C编程--进程间通信(IPC)6--综合应用实例--信号量和共享内存的使用

时间:2021-03-05 14:54:08

实例介绍:

这是一个使用共享存储交换数据的例子。其中,一个程序程序是数据处理程序,另一个程序是数据生成程序。这两个程序使用两个信号量,consumer和producer,来同步它们之间对共享内存的访问。consumer信号量指出共享存储段中的数据是否已被处理完毕,只有在数据处理完毕之后才允许数据生成程序在其中继续生成数据;producer指出数据是否已经生成在共享内存中。一个共享内存用来交换数据,所交换的数据格式由exchange结构描述。其中,成员buf用于存放数据,seq用于存放客户进程写入的顺序号。两个程序都使用一个指向该共享存储段的指针对共享内存直接进行读/写。

下面给出完整的代码。

1.用于初始化和操作信号量的头文件(myshm.h)

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


#define SHMSZ 256
union semun
{
int val;
struct semid_ds* buf;
unsigned short *array;
};


int open_semaphore_set(key_t keyval,int numsems)
{
int sid;
if(!numsems)
return -1;
if((sid=semget(keyval,numsems,IPC_CREAT|0660))==-1)
return -1;
else
return sid;
}
void init_a_semaphore(int sid, int semnum, int initval)
{
union semun semopts;
semopts.val=initval;
semctl(sid, semnum,SETVAL,semopts);
}


int semaphore_P(int sem_id)
{
struct sembuf sb;
sb.sem_num=0;
sb.sem_op=-1;
sb.sem_flg=SEM_UNDO;

if(semop(sem_id, &sb, 1)==-1)
{
printf("semaphore_P failed.\n");
return 0;
}
return 1;
}


int semaphore_V(int sem_id)
{
struct sembuf sb;
sb.sem_num=0;
sb.sem_op=1;
sb.sem_flg=SEM_UNDO;
if(semop(sem_id, &sb, 1)==-1)
{
printf("semaphore_V failed. \n");
return 0;
}
return 1;
}

2.数据处理程序

#include "myshm.h"

int main()
{
char *shm;
char buf[SHMSZ];
int shmid;
int producer, consumer, i;
consumer=open_semaphore_set(ftok("consumer",0),1);
init_a_semaphore(consumer,0,1);
producer=open_semaphore_set(ftok("producer",0),1);
init_a_semaphore(producer,0,1);
//shm=(struct exchange *)shminit(ftok("shared",0));


if((shmid=shmget(ftok("shared",0),SHMSZ, 0666|IPC_CREAT))==-1)
{
printf("shmget failed.\n");
exit(1);
}
if((shm=shmat(shmid,(unsigned char *)0,0))==-1)
{
printf("shmat failed.\n");
exit(1);
}
    buf[0]='\0';
for(i=0; ; i++)
{
semaphore_V(consumer);
semaphore_P(producer);
if(strlen(buf) != 0) {
   if(strcmp(buf,shm) != 0) {
                 printf("Data received: %s",shm);
                 strcpy((char *)buf,shm);
            }
}
else {
    printf("Data received: %s",shm);
                 strcpy((char *)buf,shm);
            }


sleep(1);
if(strcmp(shm,"end\n")==0)
{
   printf("Data received: %s\n",shm);
   break;
}
}
semctl(producer,0,IPC_RMID,0);
semctl(consumer,0,IPC_RMID,0);
}

3.数据产生程序

#include   "myshm.h"


int main()
{
char *shm, *s="end\n";
int shmid;
int producer, consumer,i;
char readbuf[SHMSZ];
consumer=open_semaphore_set(ftok("consumer",0),1);
init_a_semaphore(consumer,0,1);
producer=open_semaphore_set(ftok("producer",0),1);
init_a_semaphore(producer,0,1);


if((shmid=shmget(ftok("shared",0),SHMSZ, 0666|IPC_CREAT))==-1)
{
printf("shmget failed.\n");
exit(1);
}
if((shm=shmat(shmid,(unsigned char *)0,0))==-1)
{
printf("shmat failed.\n");
exit(1);
}
for(i=0; ; i++)
{
printf("Enter text:");
fgets(readbuf,SHMSZ,stdin);
semaphore_P(consumer);
sprintf(shm,"%s",readbuf);
semaphore_V(producer);
if(strcmp(readbuf,s)==0) {
            sprintf(shm,"end\n");
break;
}
}
return 0;
}