/*

            SC.H QNX CLIENT/SERVER HEADER FILE. POSIX VERSION

*/

/* Ñòðóêòóðà, îïðåäåëÿþùàÿ äàííûå. Ñòðóêòóðà çàïðîñà ñîâïàäàåò ñî ñòðóêòóðîé îòâåòà íà çàïðîñ*/

typedef struct

{          int data;

int cmd;

} SHMdata;

 

/*ïóòåâîå èìÿ ðàçäåëÿåìîé ïàìÿòè; àíàëîãè÷íî îïðåäåëåíèþ èìåíè ôàéëà */

char *SHMname = "DATAMEMORY";

 

typedef struct

{          sem_t access;   // ñåìàôîð äîñòóïà

sem_t answer;  // ñåìàôîð îòâåòà

sem_t query;     // ñåìàôîð çàïðîñà

} SEMAPHORE;

 

/*ñåìàôîð äîëæåí áûòü äîñòóïåí: îáúÿâëÿåìûå ñåìàôîðû äîëæíû íàõîäèòñÿ â ðàçäåëÿåìîé ïàìÿòè*/

char *SEMmemory = "SEMMEMORY";

 

void serror(char *msg)

{          printf("\nerror [%d]: %s:%s\n",getpid(),msg, strerror(errno));

exit(1);

}

 

/*

QNX SERVER. POSIX VERSION

*/

 

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/mman.h> /*îïèñàíèå ôóíêöèé äëÿ ðàáîòû ñ ðàçäåëÿåìîé ïàìÿòüþ*/

#include <semaphore.h> /*îïèñàíèå ôóíêöèé ñåìàôîðîâ*/

#include "sc.h"

 

SEMAPHORE *SEM;

SHMdata         *addr;

 

void main(int argc, char *argv[])

{          int fd, nval;

int counter;

 

/* Ñîçäàåì ðàçäåëÿåìóþ ïàìÿòü */

fd = shm_open(SHMname, O_RDWR | O_CREAT | O_EXCL, 0777);

if(fd<0)

{          printf("\ncan't open shmem (%s). Try to close it\n",strerror(errno));

                        shm_unlink(SHMname);

                        fd = shm_open(SHMname, O_RDWR | O_CREAT | O_EXCL, 0777);

                        if(fd<0) puts("can't open shmem");

            }

/* Óñòàíàâëèâàåì ðàçìåð îáëàñòè */

if(ltrunc(fd,sizeof(SHMdata),SEEK_SET)==-1) serror("set shm size error");

addr =mmap(0,sizeof(SHMdata),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

if(addr == (void *)-1) serror("mmap failed");

close(fd);

printf("\nMap address = %6.6X\n",addr);

 

/* Îòêðûòü ðàçäåëÿåìóþ ïàìÿòü äëÿ SEMAPHORE */

/* ñåìàôîðû äîñòóïíû äðóãèì - íå ðîäñòâåííûì - ïðîöåññàì òîëüêî â

ðàçäåëÿåìîé ïàìÿòè. Íóæíî îòêðûòü ïàìÿòü äëÿ ðàçäåëÿåìîãî ñåìàôîðà */

 

fd = shm_open(SEMmemory, O_RDWR | O_CREAT | O_EXCL, 0777);

if(fd<0)

{          printf("\ncan't open shmem for SEMAPHORE (%s). Try to close it\n",

                                    strerror(errno));

                        shm_unlink(SEMmemory);

                        fd = shm_open(SEMmemory,O_RDWR|O_CREAT|O_EXCL,0777);

                        if(fd<0) puts("can't open shmem for SEMAPHORE");

}

 

/* Óñòàíàâëèâàåì ðàçìåð îáëàñòè */

if(ltrunc(fd,sizeof(SEMAPHORE),SEEK_SET)== -1)

            serror("set shm size error for SEMAPHORE");

SEM = mmap(0,sizeof(sem_t), PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

if(SEM == (void *)-1) serror("mmap for SEMAPHORE failed");

close(fd);

printf("\nMap address for SEMAPHORE = %6.6X\n",SEM);

/* Îòêðûâàåì ñåìàôîðû */

if(sem_init(&SEM->access,1,1)<0) serror("sem_init/access");

if(sem_init(&SEM->answer,1,0)<0) serror("sem_init/answer");

if(sem_init(&SEM->query,1,0)<0) serror("sem_init/query");

printf("\nSERVER SEMAPHORES\n");

printf("\taccess: semid=(%d) value=(%d)\n", SEM->access.semid,SEM->access.value);

printf("\tanswer: semid=(%d) value=(%d)\n",

            SEM->answer.semid,SEM->answer.value);

printf("\tquery:  semid=(%d) value=(%d)\n", SEM->query.semid,SEM->query.value);

 

/* Îñíîâíîé öèêë ïðîãðàììû-ñåðâåðà */

counter=0;

addr->cmd = 1;

while(1)

{          if(sem_wait(&SEM->query)<0) serror("sem_wait/query");

            if(addr->cmd==0) break;

            nval = (addr->data)+100;

            (addr->data) = nval;

            counter++;

            if(sem_post(&SEM->answer)<0) serror("sem_post/answer");

            if(sem_post(&SEM->access)<0) serror("sem_post/access");

}

/* Óäàëÿåì ñåìàôîðû */

if(sem_destroy(&SEM->access)<0) serror("sem_destroy/access");

if(sem_destroy(&SEM->answer)<0) serror("sem_destroy/answer");

if(sem_destroy(&SEM->query)<0) serror("sem_destroy/query");

shm_unlink(SEMmemory);

shm_unlink(SHMname);

printf("\n\nSERVER TERMINATED\nTotal queries = %d\n",counter);

}

 

/*

QNX CLIENT. POSIX VERSION

*/

 

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/mman.h>

#include <semaphore.h>

#include "sc.h"

 

SEMAPHORE *SEM;

SHMdata         *addr;

 

void main(int argc, char *argv[])

{          int fd;

int counter;

int nval;

 

/* Îòêðûâàåì ðàçäåëÿåìóþ ïàìÿòü */

fd = shm_open(SHMname, O_RDWR, 0777);

if(fd<0) serror("can't open shmem");

 

addr = mmap(0, sizeof(SHMdata) , PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);

if(addr == (void *)-1) serror("mmap failed");

 

close(fd);

printf("\nclient[%d]: Map address = %6.6X\n",getpid(),addr);

 

/* Îòêðûòü ðàçäåëÿåìóþ ïàìÿòü äëÿ SEMAPHORE */

fd = shm_open(SEMmemory, O_RDWR, 0777);

if(fd<0) serror("can't open shmem for SEMAPHORE");

SEM=mmap(0,sizeof(SEMAPHORE),PROT_READ|PROT_WRITE,

                                    MAP_SHARED,fd,0);

if(SEM == (void *)-1) serror("mmap failed");

close(fd);

printf("\nCLIENT [%d]: Map address for SEMAPHORE = %6.6X\n", getpid(),SEM);

printf("\nCLIENT [%d] SEMAPHORES\n",getpid());

printf("\taccess: semid=(%d) value=(%d)\n", SEM->access.semid,SEM->access.value);

printf("\tanswer: semid=(%d) value=(%d)\n",

            SEM->answer.semid,SEM->answer.value);

printf("\tquery: semid=(%d) value=(%d)\n", SEM->query.semid,SEM->query.value);

 

/* Îñíîâíîé öèêë ïðîãðàììû-ñåðâåðà */

for(counter=1;counter<argc;counter++)

{          sleep(1); // çàäåðæêà (äëÿ ÷èñòîòû ýêñïåðèìåíòà)

                        /* æäåì äîñòóïà */

                        if(sem_wait(&SEM->access)<0) serror("sem_wait/access");

                        nval = atoi(argv[counter]);

                        printf("\n\t-client [%d]: count me %d",getpid(),nval);

                        addr->data = nval;

                        addr->cmd = nval;

                        sem_post(&SEM->query);

                        /* æäåì îòâåòà */

                        if(sem_wait(&SEM->answer)<0) serror("sem_wait/access");

                        printf("\n\t-client [%d]: got answer: %d", getpid(),addr->data);

}

printf("\n**    client [%d]: terminated\n",getpid());

}

 

Ïðèìåð çàïóñêà ñåðâåðà è êëèåíòîâ:

server &

client   3  5  6  &

client   8  3  9  &

client   5  1  0  &

 

 

/* LINUX CALC SERVER/CLIENT HEADER */

 

#ifndef _SC_H_

 

#define _SC_H_

 

#include <sys/ipc.h>

#include <sys/shm.h>

#include <sys/sem.h>

 

/* shared memory key */

#define SHMid 123

 

typedef struct

{              int  data;

char string[512];

int  count;

int  cmd;

} SHMdata;

 

#define SEMid 321

 

/* semaphores */

 

#define access      0

#define answer     1

#define query       2

 

/* semaphore operator */

struct sembuf sop;

 

int sem_wait(int sid, int snum)

/* function P */

{              sop.sem_num = snum; /* semaphore number */

                sop.sem_op = -1;

                return semop(sid,&sop,1);

}

 

int sem_post(int sid, int snum)

/* function V */

{              sop.sem_num = snum; /* semaphore number */

                sop.sem_op = 1;

                return semop(sid,&sop,1);

}

#endif

 

/* LINUX CALC SERVER */

 

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/mman.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include "sc.h"

 

SHMdata               *addr;

 

void serror(char *msg)

{              printf("\nserver error [%d]: %s:%s\n",getpid(),msg,strerror(errno));

                exit(1);

}

 

void main(int argc, char *argv[])

{              int nval;

                int sid;

                int shmid;

                short initarray[3] = {1,0,0}; /* access,answer,query */

 

                /* Open sh memory */

                shmid = shmget(SHMid,sizeof(SHMdata), 0777 | IPC_CREAT);

                addr = (SHMdata *)shmat(shmid,0,0);

                printf("\nserver: map address = %6.6X\n",addr);

 

                /* create and init semaphores */

                sid = semget(SEMid,3,0777 | IPC_CREAT);

 

                /* init semaphores*/

                semctl(sid,3,SETALL,initarray); /* access=1,answer=0,query=0 */

                // sem_init(&SEM->access,1,1)

                                // sem_init(&SEM->answer,1,0)

                                // sem_init(&SEM->query,1,0)

 

                /* main program loop */

                addr->cmd = 1;

                while(1)

                {              if(sem_wait(sid,query)<0)  serror("sem_wait/query");

                                if(addr->cmd==0) break;

                                nval = (addr->data)+100;

                                (addr->data) = nval;

                                if(sem_post(sid,answer)<0)  serror("sem_post/answer");

                                if(sem_post(sid,access)<0)  serror("sem_post/access");

                }

 

                /* delete semaphore */

                semctl(sid,3,IPC_RMID,0);

 

                /* delete shared memory*/

                shmctl(shmid,IPC_RMID,0);

                printf("\n\nserver terminated\n");

}

 

/* LINUX CALC CLIENT */

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/mman.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include "sc.h"

 

SHMdata               *addr;

 

void serror(char *msg)

{              printf("\nclient error [%d]: %s:%s\n",getpid(),msg,strerror(errno));

                exit(1);

}

 

void main(int argc, char *argv[])

{              int shmid;

                int semid;

                int counter, nval;

 

                /* Open sh memory */

                shmid = shmget(SHMid, sizeof(SHMdata), 0777);

                addr = (SHMdata *)shmat(shmid,0,0);

                printf("\nclient [%d]: map address = %6.6X\n",getpid(),addr);

 

                /* open semaphores */

                semid = semget(SEMid,0,0);

 

                /* main program loop */

                for(counter=1;counter<argc;counter++)

                {              sleep(1);

                                /* wait for access */

                                if(sem_wait(semid,access)<0)  serror("sem_wait/access");

 

                                nval = atoi(argv[counter]);

                                printf("\n\tclient [%d]: -Count me %d",getpid(),nval);

                                addr->data=nval;

                                addr->cmd = nval;

                                sem_post(semid,query);

 

                                /* wait for answer */

                                if(sem_wait(semid,answer)<0)  serror("sem_wait/access");

                                printf("\n\tclient [%d]: -Got answer %d",getpid(),addr->data);

                }

                printf("\n**           client [%d] terminated\n",getpid());

}