🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: be.comp.programming
Article #14281

Re: semaforen en gedeeld geheugen (linux)

#14281
From: Andy Georges
Date: Wed, 07 Mar 2001 09:07
414 lines
11940 bytes
Hello,

> Ik heb een boek dat handelt over programmeren in linux Nu zit ik aan het
> deel van gedeeld geheugen tussen 2 processen. Kan iemand dat mij eens
> uitleggen wat ik snap er niks van! Hoe doe je dat nu? 2 processen een
> stuk geheugen samen laten gebruiken?

ik heb geen tijd om hier veel uitleg te typen, maar bekijk eens de
volgende man pages. Ik zal er een voorbeeldje aanhangen achteraan deze
post. ik hoop dat ik alle code goed heb gekopieerd. er zijn vier files, in
volgorde: matrix.c matinv.h matinv.C Makefile. let erop dat sommige
codelijnen gewrapt zijn en je ze dus zelf aan elkaar zult moeten hangen. 


twizors:~$man -k shm shm_open(3) - open or create a shared memory object
shm_unlink remove a shared m emory object shmat(2), shmdt(2)       -
attach or detach shared memory shmctl(2)                - shared memory
control shmget(2)                - obtain a shared memory identifier

> # Red hat Linux 7.0 --- Kernel 2.4.1 on i586
>  2:35pm  up  1:06,  4 users,  load average: 0.10, 0.16, 0.21

i can do better ;-)
9:35am  up 258 day(s),  1:50,  2 users,  load average: 2.21, 1.69, 1.32

mvg, andy
==========================================================================
Dept. of Applied Mathematics and Computer Science, University of Ghent
Krijgslaan 281 - S9, B - 9000 Ghent, Belgium Phone: +32-9-264.47.66, Fax:
+32-9-264.49.95 E-mail: andy.georges@rug.ac.be
==========================================================================


--------------------------- matrix.c

/* Andy Georges -- 04/11/1999 */
/* Parallelle en Gedistribueerde Systemen */
/* Practicum 4 */
/* pract4.c */
/* ====================================== */

/* includefiles */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <signal.h>
#include <sys/wait.h>
#include "matinv.h"


/* prototypes */
int slave(int matrix_dimension,int nr_slaves,int slavenumber); int
master(int matrixdimension,int nr_slaves); void cleanup(int);


/* globale data */
double *b = NULL; int *sh_T = NULL; int shm_id = 0;


/* hoofdprogramma */
int main(int argc, char **argv) {


  key_t shm_key = 0; char shm_path[32] = "matrix.c"; char *shm_base =
  NULL;

  int matrix_dimension = 0; int nr_slaves = 0; int slavenumber = 0; int i
  = 0;
  
  if(argc < 4) {
    fprintf(stderr,"Niet genoeg argumenten\n"); exit(1);
  }
  
  matrix_dimension=atoi(argv[2]); nr_slaves = atoi(argv[3]);
  
  for(i=1;i<20;++i) {
    if(i != 9 && i != 15 && signal(i,cleanup) == SIG_ERR) {
      perror("signal");
 /*      exit(1);  */ /* geen exit gewoon verder doen */
    }
  }

  /* key om shared mem te verkrijgen */
  if((shm_key = ftok(shm_path,7)) == -1) {
    perror("ftok"); exit(1);
  }

  /* shared mem aanvragen orig*/
  if((shm_id =
  shmget(shm_key,2*matrix_dimension*matrix_dimension*sizeof(double)+sizeof(int
),0700 | IPC_CREAT)) == -1) {
    perror("shmget"); exit(1);
  }

  /* het adres van ons shared mem vastkrijgen */
  if(*(shm_base = (char*) shmat(shm_id,0,0)) == -1) {
    shmctl(shm_id,IPC_RMID,0); perror("shmat"); exit(1);
  }

  printf("checking ... shm_base = %x\n",shm_base);

  /* de matrix alloceren */
  b = (double*) shm_base;

  /* de teller alloceren */
  sh_T = (int*) (shm_base +
  2*matrix_dimension*matrix_dimension*sizeof(double)); 

  printf("2\n");


  if(argc == 4 && !strcmp("M",argv[1])) { /* Massster */
    return master(matrix_dimension,nr_slaves);
  }
  else if(argc == 5 && !strcmp("S",argv[1])) { /* Slaeve */
    slavenumber = atoi(argv[4]); return
    slave(matrix_dimension,nr_slaves,slavenumber);
  }
  
  return 0;
}


/* ---------------------------------------------------*/
/* masterfunctie */
int master(int matrix_dimension,int nr_slaves) {

  double* a = NULL;

  printf("Starting Massster ...\ndim = %d\nclients =
  %d\n",matrix_dimension,nr_slaves);


  /* initialiseren van de matrix a */
  if((a = (double*)
  calloc(matrix_dimension*matrix_dimension,sizeof(double))) == NULL) {
    perror("calloc"); shmctl(shm_id,IPC_RMID,0);
  }
  mat_init(a,matrix_dimension); printf("master -> a geinitialiseerd\n");

  /* initialiseren van het gemeenschappelijke geheugen */
  matinv_init(b,a,matrix_dimension); printf("master -> b
  geinitialiseerd\n");

  /* go ... */
  *sh_T = 1;

  /* wachten tot de slaves klaar zijn */
  while(*sh_T < nr_slaves+1);
  
  printf("slaves gedaan\n");

  /* geheugen vrijgeven */
  shmctl(shm_id,IPC_RMID,0);

  matinv_finalize(b,matrix_dimension); printf("Fout:
  %lf\n",mat_err(a,b,matrix_dimension));

  return 0;
}
/* ---------------------------------------------------*/



/* ---------------------------------------------------*/
/* clientfunctie */
int slave(int matrix_dimension,int nr_slaves,int slavenumber) {

  printf("Starting Slave ...\ndim = %d\nclients = %d\nslavenr =
  %d\n",matrix_dimension,nr_s
laves,slavenumber);
  
  /* wachten op onze beurt */
  while(*sh_T != slavenumber) {
    sleep(1);
  }

    /* als we dit afzetten, dan blijkt dat we de volgorde van de slaves
    die we opstarten nu
meriek */
    /* moeten nemen, ie 1, 2, 3, ... */
    /* als de sleep() wordt uitgevoerd werkt het ook als we de volgorde */
    /* wilkeurig nemen, vb.  1, 3, 2, 4, ... */


  /* ons deel van de bewerking uitvoeren */
  printf("in slave -->  waarden:\ndim = %d\nslaves=%d\nslavenr=%d\n",
         matrix_dimension,nr_slaves,slavenumber);

  matinv_body(b,matrix_dimension,
              (slavenumber-1) * matrix_dimension / nr_slaves ,
              slavenumber * matrix_dimension / nr_slaves );
  
  /* teller verhogen : beurt aan de volgende */
  printf("before shared counter = %d\n",*sh_T);
  (*sh_T) +=1 ;
  printf("after shared counter = %d\n",*sh_T);

  return 0;
}
/* ---------------------------------------------------*/


/* ---------------------------------------------------*/
void cleanup(int i) {
  if(shmctl(shm_id,IPC_RMID,0)==-1) {
    perror("shmctl"); exit(1);
  }
}


----------------------------- matinv.h

/* matinv.h, BVA, 06.10.98
           , KB, 31.10.99 */


#ifndef MATINV_H
#define MATINV_H


/* #include "bool.h"  */

//#define  true   1
//#define  false  0

typedef int bool;

/* Adresseer het element op rij i en kolom j van de matrix A. */
#define MATA(i,j)  ((a)[(i)*(n)+(j)])
#define MATBROWS   (n)
#define MATBCOLS   (2*n)
#define MATB(i,j)  ((b)[(i)*MATBCOLS+(j)])
#define MATB2(i,j) MATB(i,j+n)


#if defined(__cplusplus)
  extern "C" {
#endif
  
  

  
void mat_init(double* const a, int const n); double mat_err(double const*
const a, double const* const b, int n); double* matinv_init(double* const
b, double const* const a, int const n); bool matinv_body(double* const b,
int const n, int const i0, int const i1); bool matinv_finalize(double*
const b, int const n);

#if defined(__cplusplus)
    }
#endif


#endif /* MATINV_H */


-------------------------- matinv.C


#if !defined(__cplusplus)
#error "Dit is een C++ bronbestand. Gebruik a.u.b. een C++-compiler."
#endif


// matinv.C, BVA, 28.10.98. Voer de matrixinversielus uit voor
// een gegeven interval van iteraties.


#include <assert.h>   // assert()
#include <iostream.h> // cout
#include <math.h>     // fabs()
#include "matinv.h"   // matinv()


// Initialiseer matrix a(n x n) met bepaalde waarden.

void mat_init(double* const a, int const n)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            MATA(i,j) = 1 + (i == j) + i / 3.0 - j / 5.0;
}


// Bereken het gemiddelde kwadratische verschil tussen de
// eenheidsmatrix en het produkt van de (n x n) matrix a en de
// rechterhelft van de (n x 2n) matrix b en de eenheidsmatrix,
// en controleer dus of deze twee matrices elkaars invers zijn.
// Het resultaat ligt typisch tussen 1e-13 en 1e-16 (hoe kleiner,
// hoe beter).

double mat_err(double const* const a, double const* const b, int n)
{
    assert(a); assert(b); assert(n >= 1);

    double errsum = 0; for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            double prod = 0; for (int k = 0; k < n; k++) {
                prod += MATA(i,k) * MATB2(k,j);
            }
            errsum += (prod - (i == j)) * (prod - (i == j));
        }
    }

    return sqrt(errsum / (n * n));
}


// Initialiseer de (n x 2n) matrix b voor de inversie aan de hand van
// de (n x n) matrix a.

double* matinv_init(double* const b, double const* const a, int const n)
{
    assert(n >= 1); assert(a);

    // Vul gedeelte (0..n-1,0..n-1) op met de gegeven matrix b.
    int i; for (i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            MATB(i,j) = MATA(i,j);
    // Vul gedeelte (0..n-1,n..2n-1) op met de eenheidsmatrix.
    for (i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            MATB2(i,j) = (i == j) ? 1.0 : 0.0;

    return b;
}


// Voer stappen 0 <= i0 <= i1 <= n uit van de matrixinversie
// in de (n x 2n) matrix b.

bool matinv_body(double* const b, int const n, int const i0, int const i1)
{

  cout << "in matinv --> i0 = " << i0 << "\t\t" << "i1 = " << i1 <<endl;

    assert(b); assert(n >= 1); assert(0 <= i0 && i1 <= n);

    for (int i = i0; i < i1; i++) {
        int    j; int    pivot = i; double m = MATB(i,i);
        // Zoek pivot.
        for (j = i; j < MATBROWS; j++) {
            if (fabs(MATB(j,i)) > m) {
                m = fabs(MATB(j,i)); pivot = j;
            }
        }
        // Verwissel rij pivot met rij i.
        if (i != pivot) {
            assert(pivot > 0); for (j = i; j < MATBCOLS; j++) {
                double const t = MATB(i,j); MATB(i,j)      =
                MATB(pivot,j); MATB(pivot,j)  = t;
            }
        }
        // Reduceer rij j met rij i.
        for (j = 0; j < MATBROWS; j++) {
            if (MATB(i,i) == 0)
                return false;
            if (i != j) {
                double const f = MATB(j,i) / MATB(i,i); for (int k = i+1;
                k < MATBCOLS; k++) {
                    MATB(j,k) -= f * MATB(i,k);
                }
            }
        }
    }
    return true;
}


// Voer de laatste stap van de matrixinversie uit in de (n x 2n) matrix b.

bool matinv_finalize(double* const b, int const n)
{
    for (int i = 0; i < MATBROWS; i++) {
        assert(MATB(i,i) != 0); for (int j = 0; j < MATBROWS; j++) {
            MATB2(i,j) /= MATB(i,i);
        }
    }

    return true;
}


----------------------- Makefile

#Andy Georges
#Practicum1 P&GDS 14/10/1999
#Makefiles etc.

#Compiler
CC=gcc CPP=g++

#Flags
CFLAGS=-O2 -Wall

#Compiler Options
INCLUDE= LDPATH= LIBS=-lm

.c.o:
        $(CC) $(CFLAGS) -c $< -o $@
.C.o:
        $(CPP) $(CFLAGS) -c $< -o $@

all: matrix

matrix: matrix.o matinv.o
        $(CPP) $(CFLAGS) $(INCLUDE) $(LDPATH) -o $@ matrix.o matinv.o
        $(LIBS)
        chmod 700 $@

#object files
matrix.o: matinv.h matrix.c matinv.o: matinv.h matinv.C
Technical Details
Message-ID: <984tj3$r40$1@inf6serv.rug.ac.be>
Path: arc1-ca.pugleaf.net!supernews.google.com!sn-xit-03!supernews.com!nntp.cs.ubc.ca!torn!sunqbc.risq.qc.ca!newsfeeds.belnet.be!naxos.belnet.be!news.belnet.be!inf6serv.rug.ac.be!not-for-mail
References: <3AA24507.37053BD0@wol.be>

Show Full Headers
Complete Article Headers
X-Google-Language: DUTCH,ASCII-7-bit
X-Google-Thread: fcea4,295e319c3c2a02ba
X-Google-Attributes: gidfcea4,public
X-Google-ArrivalTime: 2001-03-07 01:16:10 PST
Path: arc1-ca.pugleaf.net!supernews.google.com!sn-xit-03!supernews.com!nntp.cs.ubc.ca!torn!sunqbc.risq.qc.ca!newsfeeds.belnet.be!naxos.belnet.be!news.belnet.be!inf6serv.rug.ac.be!not-for-mail
From: "Andy Georges" <andy.georges@nospam.rug.ac.be>
Newsgroups: be.comp.programming
Subject: Re: semaforen en gedeeld geheugen (linux)
Date: Wed, 07 Mar 2001 10:07:58 +0100
Organization: University of Ghent, Belgium
Lines: 414
Message-ID: <984tj3$r40$1@inf6serv.rug.ac.be>
References: <3AA24507.37053BD0@wol.be>
NNTP-Posting-Host: twizors.rug.ac.be
User-Agent: Pan/0.9.2 (Unix)
X-No-Productlinks: Yes