38
Processprogrammering Sida 1/38 Process- programmering höstterminen år 2003 socket() socket() bind() connect() listen() accept() väntar på klient read() anrop write() write() svar read() inkoppling

Process- programmering

  • Upload
    others

  • View
    22

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Process- programmering

Processprogrammering

Sida 1/38

Process-

programmering

höstterminen år 2003 socket() socket() bind() connect() listen() accept() väntar på klient read() anrop write() write() svar read()

inkoppling

Page 2: Process- programmering

Processprogrammering

Sida 2/38

INNEHÅLL

Kommandorad rörledning ______________________________________________4

Systemanrop _________________________________________________________4

En process startar upp en annan process i UNIX ___________________________4

Processklyvning _____________________________________________________4 Systemanrop fork ___________________________________________________________ 4

Kodbyte i process ____________________________________________________5 Systemanropet execl _________________________________________________________ 5 Systemanropet execv _________________________________________________________ 5

En process (=föräldraprocess) startar upp en process (=barnprocess) ____________6 Systemanropet wait __________________________________________________________ 6

Processtruktur ______________________________________________________7

Programmerade rörledningar ___________________________________________7

Fördefinierade fildeskriptorer __________________________________________7

Fildeskriptor________________________________________________________7

Strömpekarnamn ____________________________________________________7

Ursprunglig betydelse_________________________________________________7

STDIN ____________________________________________________________7

STDOUT __________________________________________________________7

STDERR __________________________________________________________7 systemanropet pipe __________________________________________________________ 7 systemanropet write__________________________________________________________10

Automatiskt synkronisering____________________________________________10

Några viktiga systemanrop ____________________________________________12 Systemanropet getpid ________________________________________________________12 Systemanropet getppid _______________________________________________________12 Systemanropet sleep _________________________________________________________12 Systemanropet pause_________________________________________________________12 Systemanropet exit __________________________________________________________12

Namngivna rörledningar______________________________________________12

Hur skapas en ”named pipe” __________________________________________12 Systemanropet mknod ________________________________________________________12 Systemanropet open _________________________________________________________13

SIGNALER_________________________________________________________14

Externa och interna signaler .__________________________________________14

Uppfångad signal (”Signal catching”)____________________________________14

Standardiserade signaler _____________________________________________15 Systemanropet kill ___________________________________________________________15 Systemanropet signal_________________________________________________________15

IPC = InterProcess Communication_____________________________________17

Meddelandeköer____________________________________________________18

Page 3: Process- programmering

Processprogrammering

Sida 3/38

Meddelandeköer detaljbeskrivning _____________________________________18 Systemanropet msgget________________________________________________________18 Systemanropet msgsnd _______________________________________________________19 Systemanropet msgrev________________________________________________________20 Systemanropet msgctl ________________________________________________________21

Delat minne _______________________________________________________21

Detaljbeskrivning av delat minne _______________________________________22 Systemanropet shmget________________________________________________________22 Systemanropet shmat_________________________________________________________23 Systemanropet shmdt_________________________________________________________23 Systemanropet shmctl ________________________________________________________23

Binär semafor______________________________________________________24

SEMAFORER _____________________________________________________24

Programmeringsexempel med semaforer_________________________________25

Semaforer i UNIX___________________________________________________26

En semafortabell tas i bruk____________________________________________26 Systemanropet semget________________________________________________________26

Semaforer hantering_________________________________________________27 Systemanropet semctl ________________________________________________________27

Semaforoperationer _________________________________________________28 Systemanropet semop ________________________________________________________28

Semaforanvändning _____________________________________________________29

Producent – konsument problemet______________________________________29

a) en producent , en konsument _______________________________________29

b) Flera producenter, flera konsumenter________________________________30

Hantering av IPC – objekt ____________________________________________31

Kommunikation mellan processer med uttag ______________________________31 Systemanropet socket ________________________________________________________32 Systemanropet bind__________________________________________________________33 Systemanropet listen _________________________________________________________33 Systemanropet accept ________________________________________________________33 Systemanropet connect _______________________________________________________34

Synkroniserar accept ________________________________________________34 Systemanropet connect _______________________________________________________34 Systemanropet shutdown ______________________________________________________34

Kommunikation på samma dator_______________________________________34

Kommunikation via TCP/IP –nät_______________________________________36

Hantering av IP-nummer/Internet namn _________________________________36 Systemanropet inet_addr______________________________________________________36 Systemanropet gethostbyname __________________________________________________36

Page 4: Process- programmering

Processprogrammering

Sida 4/38

Kommandoradrörledning

(MS-DOS , UNIX) “pipeline” Programmeras prog1 | prog2 | prog3 Antalet steg i rörledningen begränsas endast av datorns resurser. Utdata från ett program (en process) används som indata till ett annat program (en annan process).

Systemanrop Ett c -program kan utnyttja operativsystem kärnans (”kernel”) tjänster med sk. systemanrop (= anrop av systemfunktioner)

En process startar upp en annan process i UNIX • 2 skeden

1) processkloning med fork (processklyvning) 2) Klonen byter kod + data med execl eller execv

Processklyvning Systemanrop fork() Klyver den ursprungliga processen i:

• Föräldraprocess • Barnprocess

Båda processerna kör samma kod med samma data fork() returnerar:

• Barnprocessens processnummer i föräldraprocessen • Värdet 0 i barnprocessen • Vid misslyckande –1

Ex. main() { if(fork()) printf(”Föräldraprocess \n”); else printf(”Barnprocess \n”); }

Prog1

Prog 2

Prog 3

Page 5: Process- programmering

Processprogrammering

Sida 5/38

Programmet körs Föräldraprocess Barnprocess Eller Barnprocess Föräldraprocess Beroende på vilken process som körs först

Kodbyte i process Systemanropet execl int execl(char *name,char *arg1,char *arg2,…,char *argn,0);

• name pekare på programkodens filnamn • arg1 pekare på uppstartningsteckensträng • argi2, arg3, arg4, … pekare på varje parameter (teckensträng) • sista parametern = 0

execl exekveras:

koden byts till den kod som finns i den fil vars namn adresseras med första parametern.

Ex. Utför UNIX- kommandot ps –ax från ett c – program. (ps – kommandot i filen / bin/ps) #include<stdio.h> main() { execl(”/bin/ps”,”ps”,”-ax”,0); printf(”misslyckat kodbyte \n”); exit(8); } Systemanropet execv int execv(char *name,char *argv[]);

• name pekare på programkodens filnamn • argv tabell med pekare på övriga parametrar som behövs i execl

Ex. C –program för ps –ax med execv. #include<stdio.h> char *argv[]={”ps”,”-ax”,0}; main() { execv(”/bin/ps”,argv); printf(”Kodbyte misslyckat \n”)M

exit(8); }

Utförs endast om kodbyte misslyckas

Page 6: Process- programmering

Processprogrammering

Sida 6/38

En process (=föräldraprocess) startar upp en process (=barnprocess) 1) Processklyvning med fork() (-1 returneras vid misslyckande) 2) Barnprocess byter kod med execl eller execv 3) Föräldraprocess fortsätter med egen kod En föräldraprocess kan skapa flera barnprocess , som identifieras med processnummer, som returneras av fork i föräldraprocessen. En Föräldraprocess kan vänta på avslutningen av en barnprocess med Systemanropet wait wait(&status); wait returnerar den avslutade barnprocessens processnummer status betecknar namnet på en heltalsvariabel som får barnprocessen slutstatus som värde. Denna slutstatus innehåller bl.a. Barnprocessens slutkod (”exit code”) som vanligen är 0. OBS! I UNIX betecknar slutkoden 0 vanligen en normal avslutning av ett program Slutkoden efter senaste avslutade program finns i omgivningsvariabeln ?

• wait returnerar –1 vid misslyckande. • wait misslyckas om det inte längre finns barnprocesser vars avslutning inte

har testats med wait. • om en process skapar 3 barnprocesser lyckas 3 wait och därefter returnerar

varje följande wait –1. • wait blir ”hängande” tills någon barnprocess har avslutats vid

misslyckande returneras –1 och följande sats utförs omedelbart. • ifall en barnprocess avslutas före wait returneras processnumret och

följande sats utförs genast. • Om flera barnprocesser ha avslutats före wait returneras processnumret på

den barnprocess som avslutades först. Ex. Skriv ett program som skapar en ny process för UNIX kommandot date och

därefter meddelar att datum har skrivits ut. #include<stdio.h> main() { int status ,id; printf(”Så skrivs datum i UNIX: \n”); if(!(id=fork()))

{ execl(”/bin/date”,”date”,0); printf(”misslyckat kodbyte \n”); exit(8); } if(id= =wait(&status)) printf(”Datum utskriven \n”);

} Så skrivs datum i UNIX:

Page 7: Process- programmering

Processprogrammering

Sida 7/38

Wed Jan 7 14:25:31 1998 Datum utskrivet fork , execl eller execv , wait kan användas till process strukturering. En process kan ”delegera” arbete till en eller flera barnprocesser som i sin tur kan ”delegera” till egna barnprocesser. Resultatet från ”delegerat” arbete inväntas med wait data resultat Huvudprocess - föräldraprocess - master Slavprocess - barnprocess - slave Data och resultat skickas mellan processerna med någon data kommunikationsmetod (”rörledning”, ”fil”, ”meddelande kö”, delade variabler, kommandorad parametrar) Processtruktur Huvud

Slav1 Slav2 Slav3

Slav11 Slav12 Slav31 Slav32 Slav33

Slav21 Slav22

Ifall datakommunikation mellan processer förverkligas med filer måste beaktas att inte samma fil kan vara öppen samtidigt i flera processer

Programmerade rörledningar I dubbelriktad kommunikation måste rörledningarna flyttas från kommandoraden in i c –programmet. Begreppet FILEDESCRIPTOR Varje öppen fil i UNIX har en sk. Fildeskriptor = ett icke negativt heltal som är unik.

Fördefinierade fildeskriptorer Fildeskriptor Strömpekarnamn Ursprunglig betydelse

0 STDIN Standard Input (tangentbordet) 1 STDOUT Standard Output (bildskärm) 2 STDERR Standard Error (skärm)

En rörledning skapas med systemanropet pipe pipe(pd); // pd => int pd[2]; pd bör vara definierad som int pd[2]; En rörledning reserverar minne!

Huvud process Slav process

Page 8: Process- programmering

Processprogrammering

Sida 8/38

Returnerar: • 0 vid framgång • -1 vid misslyckande

Ex. if(pipe(pd))

{ printf(”misslyckad rörledning \n”); exit(5); }

Efter anrop av pipe(pd) innehåller tabellen pd 2 fildeskriptorer pd[0] läsning från rörledning pd[1] skrivning i rörledningen pipe(pd)

pd[1] pd[0] En fildeskriptor kan associeras med en ström pekare med systemanropet fdopen fork duplicerar rörledningens fildeskriptorer (OBS! Rörledningen dupliceras ej) Ex. int pd[2]; FILE *in, *ut; pipe(pd); in=fdopen(pd[1],”w”); /* fdopen returnerar ett strömpekar värde */ ut=fdopen(pd[0],”r”); fprintf(in,…); fscanf(ut,…); in Rörledning ut Önskas pipe(pd1) pipe(pd2)

Process

Process 1

Process 2

Page 9: Process- programmering

Processprogrammering

Sida 9/38

Stängning av en öppen fil fclose(strömpekar-namn ) eller close(fildeskriptor-värde) samma gäller för rörledning. För att 2 processer skall kunna använda samma rörledning som skapats med pipe måste den ena processen vara ”ättling” i rakt nedstigande led minst en fork i mellan. Hur kopplas en rörledning till standard input i en barnprocess till den process som skapats rörledningen med pipe.

1) Standard Input stängs i barnprocessen close(0); 2) Rörledningens läsdeskriptor dupliceras med dup(pd[0]);

dup skapar en användnings mässigt likvärdig fildeskriptor med lägsta möjliga värde (0 gjordes ledig med close(0); ) efter detta dup kan barnprocessen använda fildeskriptorn 0 för läsning från rörledningen (pd[0] kan också användas) 3) Den ursprungliga fildeskriptorn stängs i barnprocessen close(pd[0])

pd[0] pd[1] pipe(pd) fork() pd[1] 0 Hur kopplas en rörledning till standard output i en barnprocess till den process som skapats rörledningen med pipe.

1) Standard output stängs i barnprocessen close(1); 2) Rörledningens skrivdeskriptor dupliceras med dup(pd[1]);

dup skapar en användnings mässigt likvärdig fildeskriptor med lägsta möjliga värde (1gjordes ledig med close(1); ) efter detta dup kan barnprocessen använda fildeskriptorn 1 för skrivning till rörledningen (pd[1] kan också användas)

3) Den ursprungliga fildeskriptorn stängs i barnprocessen close(pd[1])

pd[0] pd[1]

fork() pipe(pd)

1 0

Föräldra process

Barn process

Föräldra process

Barn process

Page 10: Process- programmering

Processprogrammering

Sida 10/38

Dubbelriktad kommunikation mellan barnprocess och föräldraprocess. Föräldraprocessen bör skapa 2 rörledningar före fork. pipe(pd1) pd1[1] 0 pipe(pd2) pd2[0] 1 Barnprocessen kan byta kod efter att kommunikation med rörledning vid standard input och standard output gjorts möjlig OBS! Alla deskriptorer som inte används vid kommunikation med rörledning bör

helst stängas. OBS!! Data kan bli ”hängande” i en rörledning trots att en process försöker läsa ut

detta data. Medicin systemanropet fflush(strömpekar namn); i den skrivande processen. Eventuell data i rörledningen ”pressas” då ut.

Data kan skickas till en för skrivning öppnad fil (rörledning) även på basen av fildeskriptorn med systemanropet write write(fd,spek,n);

• fd fildeskriptor • spek pekare på en byte i minnet, t.ex. på en teckensträng • n antalet tecken som skall skrivas

returnerar:

• Ett heltal = antalet skrivna tecken (vanligen n) • Värdet –1 vi misslyckande

Ex. if(write(pd[1],”abc”,3) = = -1) printf(”write misslyckade \n”);

En rörledning kan innehålla högst 5120 byte i UNIX OBS! Försök att skriva i en rörledning med write leder till felmeddelandet ”broken

pipe” om rörledningen läsända är stängd. Den skrivande processen avbryts.

Automatisk synkronisering Om en process försöker läsa från en tom rörledning blir processen väntande på data. Den väntande processen kan fortsätta när en annan process skrivit data i rörledningen. fflush framtvingar förutsatt att data finns i rörledningen. En fildeskriptor kan även användas för läsning av data från en fil (rörledning). read(fd, minnesadress, n);

Förälder Barn

Page 11: Process- programmering

Processprogrammering

Sida 11/38

• fd fildeskriptor • minnesadress pekare på en plats i minnet, t.ex. en teckentabell, till vilken

informationen läses (datatyp void * eller char*)

• n antalet byte som skall läsas Returnerar

• Antalet lästa tecken (byte vanligen) • -1 vid misslyckande

Exempel int antal; char tab[100]; if((antal =read(pd[0],tab,3))==-1) { printf(”read misslyckade \n”); exit(1); } printf(”%d byte lästes \n”, antal); Data från en process till en barnprocess kan förmedlas till barnprocessen i samband med barnprocessens kodbyte. Parametrarna i execl eller execv förmedlas. Parametrarna identifieras i barnprocessen som kommandoradparametrar. Med sprintf/sscanf kan programmet skriva/läsa från en given tabell. Tabellens adress som första parameter. Skärm Med execl Tangentbord X X realtal X Föräldraprocess #include<stdio.h> float x; int pid,stat; char strang[50]; main() { printf(”Ge ett realtal \n”); scanf(”%f”,&x); if(!(pid=fork())) { sprintf(strang,”%f”,x); execl(”barn”,”barn”,strang,0); } } Barnprocessen skall kunna starts från filen barn i samma katalog.

föräldraprocess

barnprocess

Page 12: Process- programmering

Processprogrammering

Sida 12/38

Barnprocess #include<stdio.h> main(int argc,char *argv[]) { float x; sscanf(argv[1],”%f”,&x); printf(”Realtalet %10.3f inmatades \n”, x); }

Några viktiga systemanrop getpid() returnerar processens processnummer getppid() returnerar föräldraprocessens process nummer sleep(t) den anropade processen väntar t sekunder t>=0 pause() den anropade processen väntar exit(slutkod) processen avslutas med given slutkod heltal>=0 0=normalt

Namngivna rörledningar (”Named pipes”)

• Finns i UNIX System V , IRIX , Solaris • Versioner i UNIX -lab har både BSD och System V egenskaper

En namngiven rörledning är ett objekt med eget namn i en katalog (jfr. fil, länk) Ett pipe -objekt igenkänns med ett p som första tecken efter ls –l (- för fil , d för katalog). En ”named pipe” är som en fil, som en process skriver och en annan process läser från. OBS! Dessa två processer behöver inte vara ”släkt” via en eller flere fork-

relationer som är nödvändigt för pipe -kommandot! OBS!! Flera processer kan samtidigt ha ett rörlednings objekt öppet både för

läsning och skrivning (ej möjlig för filobjekt)! Hur skapas en ”named pip”!

1) UNIX kommandot /etc/mknod 2) Systemanropet mknod i ett c -program

1) UNIX kommandot mknod

/etc/mknod pipename p

Härvid skapas ett objekt med namnet pipename i innevarande katalog. Detta objekt syns i katalog förteckningen efter ls eller ls –l objektet har naturligtvis även en skyddskod.

2) Systemanropet mknod

mknod(char *pipename,int mode,int dev);

• pipename pekare på teckentabell som innehåller namnet (’\0’-avslutar sträng)

Page 13: Process- programmering

Processprogrammering

Sida 13/38

• mode = 0010abc abc = skyddskod

• dev saknar betydelse t.ex dev=0 Returnerar

• 0 vid framgång • -1 vid misslyckande

Ex. mknod(”pipe1”,0010777,0); Skapar en ”named pipe” med namnet ”pipe1” i innevarande katalog.

Fritt fram för alla att använda ”pipe1” skyddskod = 777 ”pipe1” skall synas i katalogförteckningen

Ett rörledningsobjekt kan användas via fildeskriptor och/eller strömpekare. En fildeskriptor till en fil eller en ”named pipe” skapas med: int open(char *objektnamn,int mode);

• objektnamn pekare på teckentabell som innehåller namnet som c -sträng • mode = 0 – öppna för läsning

1 – öppna för skrivning 2 – öppna för både läsning och skrivning

Returnerar: • en fildeskriptor (icke negativ) • -1 vid misslyckande

Ex. ”named pipe” ”pipe1” finns Process1 Process2 int pd1; int pd2; --------------- -------------------- pd1=open(”pipe1”).1); pd2=open(”pipe1”,0); /*process1 skriver */ /*process2 läser */ pipe1 Samma exempel med Strömpekare Process1 Process2 FILE *in; FILE *ut; --------------- -------------------- in=fopen(”pipe1”).”w”); ut=fopen(”pipe1”,”r”); ---------------- ---------------------- fprintf(in,…); fscanf(ut,….);

Process1 Process2

Page 14: Process- programmering

Processprogrammering

Sida 14/38

/*process1 skriver */ /*process2 läser */

SIGNALER Kommunikation utan informationsöverföring. De normala förloppet hos en process kan avbrytas av en signal. Ex. En process i ett processfönster. Ctrl-c avslutar processen. Ctrl-c genererar en

signal som skickas till den process som skall exekveras i processfönstret. Ex2. kill 119

Detta UNIX kommando skickar en signal till processen med processnumret 119 vanligen avslutas processen, om kill -kommandot givare äger processen.

Externa och interna signaler . Interna signaler skapas av en exekverande process. Exempel:

- Ogiltig adress - Felaktig instruktion - Spill vid flyttalsoperation - Skrivning av information i en rörledning med stängd lösända

Externa signaler - Från tangentbordet t.ex. Ctrl-c - Från andra processer systemanropet kill - Från UNIX kommandorad kommandot kill

Uppfångad signal (”Signal catching”) Alla signaler utom en (SIGKILL) kan göras uppfångbara En uppfångad signal kan

- ”trigga” exekveringen av en funktion - Ignoreras

En process avslutas inte av en uppfångad signal. 15 standardiserade signaler med standardiserade signalnamn dessutom implementerings beroende signaler. Varje signaltyp har

• Signalnummer (1….15 standardiserade signaler) • Signalnamn som definieras i signal.h

Signalnamn rekommenderas i c- program

Page 15: Process- programmering

Processprogrammering

Sida 15/38

”Standardiserade” signaler Nummer Namn Beskrivning 1. SIGHUP ”terminal hangup” skapas efter avslutad förbindelse 2. SIGINT Terminal avbrott. Genereras vanligen med tangenten ctrl-c

(eller break eller del) 3. * SIGQUIT Terminal avbrott med minnesutdrag (”core dumb”) genereras

med Ctrl-\ 4. * SIGILL Genereras av ogiltig maskininstruktion 5. * SIGTRAP Spårningsavbrott (”trace trap”) används vid avlusning 6. * SIGIOT Genereras av IOT -instruktion används vid avlusning 7. * SIGEMT Genereras av EMT –instruktion kan användas av processor

som saknar flyttalsoperationer 8. * SIGFPE Genereras om flyttals operation förorsakar spill 9. SIGKILL Kan ej uppfångas genereras bl.a. av kill -9 processornummer 10. * SIGBUS Bussfel vanligen illegal pekarhantering i c- program 11. * SIGSEGV Segmenteringsfel

• Illegal pekarhantering • Överskrivning av tabellgräns

12. * SIGSYS Genereras av dåligt argument i systemanrop 13. SIGPIPE Försök att skriva i en rörledning med oöppnad läsända. 14. SIGALRM Genereras av systemanropet alarm signal efter önskat antal

sekunder ex. Alarm(10): pause(); /* pausen avbryts efter 10 sekunder */

15. SIGTERM Genereras av UNIX kommandot kill processnummer * Betyder att signalen ger minnesutdrag (”core dump”) – en fil

Med systemanropet : kill(processnummer , signalnummer); Kan en process sända en signal till en annan process Ex. kill(119,SIGTERM);

Samma som UNIX kommandot kill 119 Returnerar:

• 0 vid framgång • -1 vid misslyckande

Upp fångning av signaler ställs in med systemanropet signal(signalnummer,funkpek);

deklareras i signal.h. Den funktion som adresseras exekveras då signalen kommer. Om funkpek=SIG_IGN ignoreras signalen då den kommer. Om funkpek=SIG_DFL träder grundinställningen (”defalut”) för ifrågavarande signal i kraft. En inställning som görs med signal(signalnummer, funpek)

Page 16: Process- programmering

Processprogrammering

Sida 16/38

gäller en och endast en signal med given nummer om funkpek≠SIG_IGN och funkpek≠SIG_DFL.

Returnerar: • Pekare på den funktion som ifrågavarande signaltyp är inställd på från

tidigare • Eller värdet SIG_IGN eller SIG_DFL • -1 vid misslyckande

Ex. Skriv ett program som kvitteras 2 Ctrl-c med texten ”Ctrl-c uppfångad” och avslutas av den tredje Ctrl-c. #include<signal.h> #include<stdio.h> /* *igen är en variabel vars värde är en adress till en void - funktion */ void (*igen)(); void testfunk() { printf(”Ctrl-c uppfångad \n”); } main() { signal(SIGINT, testfunk); igen=signal(SIGINT, testfunk); printf(”tryck Ctrl-c \n”); pause(); signal(SIGINT, igen); printf(”tryck Ctrl-c\n”); pause(); /* eventuellt signal(SIGINT,SIG_DFL); */ printf(”tryck Ctrl-c \n”); pause(); } programmet körs :> tryck Ctrl-c Ctrl-c uppfångad tryck Ctrl-c Ctrl-c uppfångad tryck Ctrl-c :> Deklaration av funktion signal void ( *signal ( int sig , void ( *funk () ) ) (); signal returnerar en pekare på en void- funktion som andra parameter har signal namnet på en void- funktion.

Page 17: Process- programmering

Processprogrammering

Sida 17/38

void f1() { ……… } void f2() { ………. } main() { void (*funknamn)();

signal(SIGINT,f1); funknamn=signal(SIGINT,f2); /* variabeln funknamn har f1 som värde */

} signal returnerar en pekare på senast inställda void funktion för samma signal.

IPC = InterProcess Communication En samling systemanrop för processkommunikation ursprungligen i UNIX System V finns med i moderna UNIX – varianter (Solaris, IRIX, Linux) IPC innehåller 3 slags kommunikationsverktyg.

• Meddelandeköer (”message queue”) • delat minne (”Shared memory”) • Semaforer (”Semaphores”)

Rörledningar (”pipe”) P1 P2 P1 ,P2 processer Meddelande kö P1 P2

Page 18: Process- programmering

Processprogrammering

Sida 18/38

Delat minne minne P1 write write P2 Read read Semaforer behövs för att hindra ”rådd” av delat minne som många processer använder!

Meddelandeköer En meddelandekö skapas och/eller tas i bruk med systemanropet msgget (En process skapar övriga tar i bruk) Ett budskap läggs i en meddelandekö med systemanropet msgsnd Ett budskap avläses från en meddelandekö med systemanropet msgrcv En meddelandekö raderas eller tillståndet hos en meddelandekö avläses med systemanropet msgctl Användning av meddelandekö förutsätter följande inkluderingsfiler

• sys/types.h • sys/ipc.h • sys/msg.h

Samma meddelandekö kan samtidigt användas av flera processer i vardera riktningen ”öronmärkta meddelande”

Meddelandeköer detaljbeskrivning En existerande meddelandekö karakteriseras av en nyckel ”key” – ett heltals värde. msgget: int msgqid; msgqid=msgget(nyckel, köflaggor);

En s.k. köindikator returneras vid framgång (icke negativa heltal) misslyckande –1 • köflaggor Ett heltal som vanligen byggs upp med ”bitwise or” –operatorn

Komponenter:

Page 19: Process- programmering

Processprogrammering

Sida 19/38

• Ett heltal som betecknar skyddskod (vanligen oktal) ex. 0777

• Symboliska värdet IPC_CREAT → kö skall skapas för given nyckel ifall kön ej redan existerar.

• Symboliska värdet IPC_EXCL → kön skapas av anropade process om kön redan existerar misslyckas det

OBS! Som nyckel kan även användas symboliska värdet IPC_PRIVATE betydelse, se boken eller man msgget. Process1 Process2 #define MSGKEY 75 #define MSGKEY 75 ----------------------- ---------------------------- int msgqid; int msgqid; ----------------------- ---------------------------- msgqid=msgget(MSGKEY,0777| msgqid=msgget(MSGKEY,0777| IPC_CREAT); IPC_CREAT); En för alla användare brukbar meddelandekö med nyckel MSGKEY skapas av process1 eller process2 kön tas i bruk av båda processerna. Översända meddelande bör sparas i teckentabellfält i poster av typ

struct msgform { long mtype; char mtext[n]; }; mtype betecknar meddelandets typ (”öronmärke”) Ex. Placera ett heltals värde på en meddelandekö struct msgform msg1; int *pint,a; ----------------- scanf(”%d”,&a); pint=(int*)msg1.mtext; *pint=a; msg1.mtype=5; /* t.ex */ msgsnd(…..); Systemanropet msgsnd: msgsnd(köidentifikator,msgpek,size,msgflag);

• köidentifikator det värde som msgget returnerar • msgpek en pekare på en post med datatypen struct msgform • size heltal som anger meddelandets längd (hur många byte) • msgflag ett heltal värde som definierar åtgärd ifall meddelande inte ryms i

kön • msgflag=0 anropad process väntar tills det finns plats i kön • msgflag= IPC_NOWAIT msgsnd misslyckas

Page 20: Process- programmering

Processprogrammering

Sida 20/38

Returnerar: • 0 vid framgång • -1 vid misslyckande

Ex. En process läger sitt eget processnummer på en meddelandekö meddelandetstyp=1 #define MSGKEY 75 struct msgform { long mtype; char mtext[50]; }; int msgqid , *pint; struct msgform msg; msgqid=msgqid=msgget(MSGKEY,0777|IPC_CREAT); pint=(int*)msg.mtext; *pint=getpid(); msg.mtype=1; msgsnd(msgqid,&msg,sizeof(int),0); Systemanropet msgrcv:

int msgrcv(köidentifikator,msgpek,maxsize,typ,msgflag);

• köidentifikator det värde som msgget returnerar • msgpek en pekare på den post av typen struct msgform som skall ta i mot

meddelandet • maxsize teckentabellens storlek i den post som utpekas av msgpek • typ betecknar typen på mottaget meddelande

• typ= 0 första meddelandet i kön • typ= positivt heltal först meddelandet i kön med given typ • typ= negativt heltal första meddelandet i kön vars typ är

minsta möjliga heltal mindre än eller lika med absoluta värdet av given typparameter. T.ex. om kön innehåller meddelande av typ 1,2,3 och parametern typ=-2 avläses meddelandet med typvärdet 1

• msgflag heltalsvärde som definierar åtgärd ifall kön är tom eller meddelandets längd > maxsize

• msgflag=0 anropande process blir och vänta på meddelande av rätt typ. msgrcv misslyckas om meddelandet är fö r långt

• msgflag= IPC_NOWAIT • msgflag= MSG_NOERROR ett överlångt meddelande

avkortas till maxsize Returnerar:

• meddelandetslängd (antal byte) vid framgång • -1 vid misslyckande

Page 21: Process- programmering

Processprogrammering

Sida 21/38

Ex. En process avläser ett meddelande av typ 1 maximilängd på meddelandet är 256 byte struct msgform { long mtype; char mtext[256]; }msg; int imsgqid; msgrcv(msgqid,&msg,256,1,0); Systemanropet msgctl: msgctl(köidentifikator,cmd,bufpek);

• köidentifikator returneras av msgget • cmd ett heltal som definierar hanterings åtgärd

• cmd= IPC_RMID kön raderas bufpek saknar betydelse bufpek=0 • cmd= IPC_STAT meddelandeköns statusinformation kopieras till

fältena i den post som utpeckas av bufpek • cmd= IPC_SET meddelandeköns status ställs in enligt fältena i den

post som bufpek adresserar • bufpek pekare på en post med type struct msqid_ds (se inkluderingsfilerna

/usr/include/sys/msg.h och /usr/include/sys/ipc.h) Returnerar:

• 0 vid framgång • -1 vid misslyckande

Delat minne

minne P1 Processerna P1 och P2 använder Samma fysiska minnesplatser P2 t.ex. 64 byte Skapa/taibruk gemensamt minne systemanropet shmget En process skapar och tar i bruk övriga processer tar i bruk. Skapat gemensamt minne skall ”inbakas” i minnets adressrymd systemanropet shmat Efter detta är det delade minnet åtkomligt via en pekare som returneras av shmat (shmat måste exekveras av varje process som använder samma delade minne) .

Page 22: Process- programmering

Processprogrammering

Sida 22/38

Ett delat minne löskopplas från adressrymden för en process med systemanropet shmdt Tillståndet hos ett delat minne hanteras med systemanropet shmctl Som även används vid frigivning av delat minne. Endast en process friger!

Detaljbeskrivning av delat minne

Ett existerande delat minne måste ha en sk. Nyckel (”key”) som är ett heltalsvärde. int shmget(key_t key,int size,int shmflag);

• key nyckelvärdet (samma i varje process som använder samma delat minne)

• size hur många byte • shmflag bitmönster som vanligen skapas med | -operatorn (”bitwise or”) en

komponent är skyddskoden (9bit) som vanligen ges i oktalform t.ex 0777 andra komponenter de symboliska värdena IPC_CREAT eller IPC_EXCL

• IPC_CREAT skapar ifall inte finns • IPC_EXCL processen är den som skapar måste vara!!

OBS! Som parameter ”key” kan även användas IPC_PRIVATE Returnerar:

• identifikator för delat minne (icke negativt) • -1 vid misslyckande

Ex. Process1 Process2 #define shmkey 80 #define shmkey 80 ---------------------- ----------------------- int shmid; int shmid; if((shmid=shmget(shmkey,128, if((shmid=shmget(shmkey,128,

0777|IPC_CREAT))!=-1) 0777|IPC_CREAT))!=-1) { /* programkod */} { /* programkod */} else /* error */ else /* error */ Detta betyder att ett delat minne å 128 byte skapas och tas ibruk i process och process2. Inga användarbegränsningar (skyddskod 0777). Nödvändiga inkluderingsfiler för delat minne

• sys/types.h • sys/ipc.h • sys/shm.h

Page 23: Process- programmering

Processprogrammering

Sida 23/38

Systemanropet shmat void *shmat (int shmid,void *shmaddr, int shmflag);

• shmid identifikator värdet som returnerades av shmget • shmaddr önskad begynnelseadress för delat minne shmaddr=0

(=pekarvärdet NULL) betyder att UNIX väljer begynnelseadress • shmflag bitmönster vanligen 0 eller SHM_RND eller SHM_RDONLY

eller SHM_RND|SHM_RDONLY • SHM_RND önskad begynnelse adress shmaddr avrundas till

närmaste möjliga värde • SHM_RDONLY betyder att anropade process får endast läsa

delat minne Returnerar:

• void pekare på det delade minnesområde • -1 vid misslyckande

Ex. Förverkliga en gemensam teckentabell Process1 Process2 char *p; char *p; int shmid; int shmid; p=(char*)shmat(shmid,0,0); p=(char*)shmat(shmid,0,0); p[7]=’a’; UNIX har valt begynnelseadress för delat R/W minne i process1 och process2 Systemanropet shmdt(void *shmaddr); Utpekat delat minne frånkopplas från processens adressrymd Returnerar:

• 0 vid framgång • -1 vid misslyckande

Systemanropet int shmctl(int shmid, int cmd, struct shmid_ds *buf);

• shmid identifikator värde • cmd IPC_RMID eller IPC_STAT eller IPC_SET

• IPC_RMID delat minne raders (friges) parameter buf utan betydelse kan vara buf=0

• IPC_STAT det delade minnet status information kopieras till den post som adresseras av buf

• IPC_SET det delade minnets status ställs in av informationen i den post som adresseras av buf

Page 24: Process- programmering

Processprogrammering

Sida 24/38

• buf är en pekare på en post av type struct shmid_ds (se inkluderingsfiler sys/shm.h och sys/ipc.h)

Returnerar: • 0 vid framgång • -1 vid misslyckande

Ex. shmctl(shmid,IPC_RMID,0);

Radering av delat minne (frigivning) motsägelsefrihet bör garanteras vid hantering av delat minne (”consistency”) Ex2. 2 processer hanterar samma tabell å 256 byte Process1 Process2 Uppdatera 50 byte UNIX byter Läser 256 byte Uppdatera 206 byte UNIX bytte körbar process mitt i uppdateringen av gemensam tabell Resultat: Process2 avläste en delvis uppdaterad tabell

Behövs: Verktyg som hindrar UNIX att byta körbar process mitt i en uppdatering av delat minne. Sådant verktyg är en semafor

Binär semafor Processkö Packet : Binär variabel Binär variabel: 1 = grönt 0 = rött Processerna i processkön väntar på att en röd semafor blir grön motsägelsefrihet uppnås med semaforer

SEMAFORER Binär semafor: Hantering kan börja endast om semaforen är grön, röd semafor

väntar i semaforens processkö tills processen ser en grön semafor efter hantering ändras semaforen till grön. Semaforhantering bygger på två (2) fundamentala semafor- operationer P och V.

Page 25: Process- programmering

Processprogrammering

Sida 25/38

C- liknande pseudo- kod för P och V operationer semaphore s=init_s; /* s heltal ≥ 0 */ /* init_s ≥ 0 är begynnelsevärde */ void P(semaphore s) { [if s>0 s=s-1;

else { enter_queue();] pause( ); P(s); }

} [Programkod ;] processbytesförbud för UNIX med programkod exekvering.

• s>0 → grön semafor • s=0 → röd semafor

Om semaforen är grön kommer processen vidare. Om semaforen är röd måste processen vänta med pause() tills den blir uppväckt av en annan process. En uppväckt process anropar P(s). En process som anropar P(s) kommer inte vidare innan den ser en grön semafor. Semaforen kan bli röd då processen kommer vidare. void V(semaphore s) { [ s++; if(!empty(process_queue)) wake_up(process_in_queue);] } [Programkod ;] processbytesförbud för UNIX med programkod exekvering. V- operationen gör semaforen grön om den varit röd och väcker upp minst en process av de processer som väntar på grönt i semaforkön. Programmeringsexempel med semaforer Sk. Ömsesidig uteslutning , N st processer, som hanterar samma delat minne. Den programkod som hanterar delat minne är exempel på en sk. kritisk sektion. Processernas kritiska sektioner skall utesluta varandra. Program med pseudokod semaphore s=1; /* process_i, i=1,2,3,---,N*/ while(1) { Ej_kritsk_sektion_i();

P(s); kritsk_sektion_i(); V(s);

}

Page 26: Process- programmering

Processprogrammering

Sida 26/38

Semaforen är här binär eftersom den initialiseras till 1. En semafor som initialiseras till N>1 är en heltalssemafor. Binär semafor Blir alltid röd efter en P-operation Blir alltid grön efter en V-operation Heltalssemafor Kan bli röd efter en P-operation Blir alltid grön efter en V-operation

Semaforer i UNIX En semafortabell (1 eller flera semaforer) skapas/tas i bruk med systemanropet

semget Semaforoperationer utförs med systemanropet semop En semafortabell hanteras/raderas med systemanropet semctl Nödvändiga inkluderingsfiler

• sys/types.h • sys/ipc.h • sys/sem.h

En semafortabell tas i bruk int semget(key_t key,int count,int semflg);

• key heltalsnyckel, samma i alla processer • count antalet semaforer • semflg liknande bitmönster som i msgflg, shmflg

Returnerar: • En semaforidentifikator vid framgång • -1 vid misslyckande

Ex. 2 processer använder samma 3 semaforer Process1 Process2 #define SEMKEY 80 #define SEMKEY 80 ------------------------- -------------------------- int semid; int semid; ------------------------- ------------------------- semid=semget(SEMKEY,3, semid=semget(SEMKEY,3,

0777|IPC_CREAT); 0777|IPC_CREAT); Fritt fram att använda dessa 3 semaforer (skyddskod 0777)

Page 27: Process- programmering

Processprogrammering

Sida 27/38

Semaforer hantering int semctl(int semid, int semnum, int cmd, union semun {

int val; struct semid_ds *buf; unsigned short *array; }arg);

• semid den semaforidentifikator som returnerades av semget • cmd symboliskt heltalsvärde som anger hurudan operation utförs av

semctl. • GETVAL värdet på semaforen med index semnum

returneras (fjärde parameter behövs ej, kan sättas till 0) • SETVAL semaforen med index semnum får värdet arg.val

(fjärde parameter skall vara ett heltal) • GETPID processnummer returneras för den process som

senast avläste eller ändrade värdet på semaforen med index semnum i semafortabellen.

• GETNCNT ett heltal ≥ 0 returneras, detta heltal anger antalet processer, som väntar på att semaforen med index semnum skall inkrementeras (ifall index =+1 väntar processerna på en V-operation)

• GETZCNT ett heltal ≥ 0 returneras, detta heltal anger antalet processer som väntar på att semaforen med index semnum skall få värdet 0

• GETALL värden på alla semaforer kopieras till tabellen arg.array.(semnum ej betydelse t.ex.0)

• SETALL semafortabellens semaforer får nya värden från tabellen arg.array (semnum ej betydelse)

• IPC_RMID semafortabellen raderas. Alla processer som köar till någon av semaforerna väcks upp.

• IPC_STAT semafortabellen status info sparas i den post som arg.buf adresserar. Denna post har datatypen struct semid_ds och definieras i sys/sem.h och sys/ipc.h

• IPC_SET semafortabellen får nya status info från den post som arg.buf adresserar

Returnerar: • 0 utan för cmd=GETVAL, GETPID, GETNCNT eller GETZCND • -1 vid misslyckande

OBS! Initialisering endast av en process! Ex. int semval; semctl(semid,0,SETVAL,0); semval=semctl(semid,0,GETVAL,0); ------------------------------------------------------ semctl(semid,0,IPC_RMID,0);

Page 28: Process- programmering

Processprogrammering

Sida 28/38

Semafor med index 0 i semafortabellen får värdet 0.Detta värde tilldelas semval, Till sist raderas hela tabellen. Semaforoperationer Utförs med anrop av systemanropet int semop(int semid,struct sembuf *ops,int nsops);

• semid returneras av semgeet • ops pekare på en tabell med semaforoperationen • nsops antalet semaforoperationer

En semaforoperation specificeras med en post av datatypen struct sembuf , som deklareras i inkluderingsfilen sys/sem.h struct sembuf { short sem_num; /* index i semtab */ short sem_op; /* semaforoperation */ short sem_flg; /* semafor flagga */ };

• sem_op definierar semaforoperationen • sem_op < 0 om semaforvärde + sem_op ≥ 0 . Utförs operationen:

semaforvärde +=sem_op. Den anropande processen fortsätter. Annars ingår den anropande processen i ett väntetillstånd med beaktande av värdet på semflg. Efter väntetillståndet görs ett nytt försök att utföra operationen (i en P -op är sem_op=-1)

• sem_op > 0 nu utförs alltid semaforvärdet += sem_op. Samtidigt

väcks alla processer som väntar på inkrementering av denna semafor (i en V-op är sem_op=+1)

• sem_op = 0 Om en semaforvärde = = 0 fortsätter den anropande processen, annars ingår den anropande processen i ett väntetillstånd med beaktande av värdet på sem_flg. En väntande process väcks upp och testar semaforen igen då någon annan process ändrar semaforvärdet till 0.

• Sem_flg skall få värdet IPC_NOWAIT, SEM_UNDO eller 0 • IPC_NOWAIT en anropande process förhindras att ingå i ett

väntetillstånd varvid semaforoperationen avslutas med retur värdet –1

• SEM_UNDO Effekterna av gjorda semaforoperationen elimineras för en avslutad process.

• Vanligen används sem_flg=0 Returnerar:

• Det semaforvärde som skapas av den sista operationen i tabellen ops • -1 vid misslyckande

Page 29: Process- programmering

Processprogrammering

Sida 29/38

Ex. En process skall utföra P- och V –operation på en semafor struct sembuf p_op,v_op; p_op.sem_op=-1; /* semväre */ p_op.sem_num=0; /* index */ p_op.sem_flg=0; / * normalfal */ v_op.sem_op=1; /* semvärde+1 */ v_op.sem_num=0; v_op.sem_flg=0; semop(semid,&p_op,1); /* P-operation */ ---------------------------- semop(semid,&v_op,1); /* V-operation */ Semaforanvändning Många processer, samma semafor

• semget varje process • semctl initialisering en process • semop varje process

( Varje process skall bygga upp egna semaforoperationer i tabeller med struct sembuf poster)

Producent – konsument problemet a) en producent , en konsument

Producenten skickar värden till konsumenten via en kö med längden N. Producenten Konsumenten N st köplatser 2 heltalssemaforer

TOM initialiserad till N FULL initialiserad till 0

Pseudokod för producent och konsumentprocessen (heltalsbuffert) /* delat minne */ int buffer[N],in=0,ut=0; /* semaforer /* semaphore TOM=N,FULL=0;

/* producentprocess */ int tal; while(1) {

producera(&tal); P(TOM);

buffer[in]=tal; in=(in+1)%N;

V(FULL);

Page 30: Process- programmering

Processprogrammering

Sida 30/38

}

/* konsumentprocess */ int tal; while(1) {

P(FULL); tal=buffer[ut];

ut=(ut+1)%N; V(TOM); Konsumerat(tal); }

b) Flera producenter, flera konsumenter

Prod1 Con1 Prod2 Con2 Prod3 Con3

Problem: Alla producenter använder samma index -variabel för att placera heltal i kön. Alla konsumenter använder samma index -variabel för att hämta heltal från kön. Lösning: Ömsesidig uteslutning av producenten med binär semafor SEMIN som

initialiseras till 1. Ömsesidig uteslutning av konsumenten med binär semafor SEMUT som initialiseras till 1.

Pseudokod /* delat minne */ int buffer[N],in=0,ut=0; /* 4 semaforer /* semaphore TOM=N,FULL=0,SEMIN=1,SEMUT=1; /*varje producent process */ int tal; ¨while(1) { producera(&tal); P(TOM); P(SEMIN); buffer[in]=tal; in=(in+1)%N; V(SEMIN); V(FULL); } /* varje konsument process */ int tal; while(1) { P(FULL); P(SEMUT); tal=buffer[ut];

Page 31: Process- programmering

Processprogrammering

Sida 31/38

ut=(ut+1)%N; V(SEMUT); V(TOM);

konsumera(tal); }

I UNIX skapas en semafortabell med 4 semaforer (semget) som initialiseras med semctl i en process. Varje par av semaforoperationer kan förverkligas med ett anrop av semop om den andra parametern är namnet på en tabell med 2 poster av datatypen struct sembuf. Det delade minnets storlek är: (N+2)*sizeof(int) i shmget

- N heltal för buffern - 1 heltal för in - 1 heltal för ut

int *pint; ----------- pint=(int*)shmat(shmid,0,0); ------------- ⇒ buffer pint[0],pint[1],……,pint[N-1]; index in är pint[N] index ut är pint[N+1] Hantering av IPC – objekt med UNIX-kommandon Visa : ipcs Radera : ipcrm

Kommunikation mellan processer med datakanaler (” SOCKET”)

Ursprungligen 1981 i BSD UNIX. Finns med i praktiskt taget alla nya UNIX (LINUX, SOLARIS, IRIX). Kan användas: för kommunikation mellan processer

- Samma dator - Olika dator

Teknik: Dataströmmar via uttag Översikt:

• Serverprocesser • Klientprocesser

Server Klient Server Klient

Page 32: Process- programmering

Processprogrammering

Sida 32/38

SERVER : KLIENT: socket() socket() bind() connect() listen() accept() väntar på klient read() anrop write() write() svar read() Server bör ha utfört accept då klienten utför connect vardera processer bör skapa ett eget uttag med systemanropet socket. Server bör koppla in sin kommunikationsadress med systemanropet bind. Serverns kommunikations kö skapas med systemanropet listen. Servern inväntar en klient med systemanropet accept. Klienten kopplar sitt uttag till serverns adress med systemanropet connect. Kommunikation t.ex. med synkroniserade par av read och write. Server Klient socket socket Kommunikation Inkluderingsfiler

• sys/types.h • sys/socket.h

Kompilering i Solaris: cc …… -lsocket Systemanropet socket() int socket(format,typ,protokoll);

• format symbolisk heltalsvärde betecknar uttagets sk. adressfamilj • AF_UNSPEC ospecificerad

inkoppling

Page 33: Process- programmering

Processprogrammering

Sida 33/38

• AF_UNIX kommunikation på samma UNIX -dator kräver inkluderingsfilen sys/un.h

• AF_INET kommunikation över ett TCP/IP nät • Övriga värden se inkluderingsfilen sys/socket.h

• typ Symboliskt heltalsvärde, definierar data kommunikations interna struktur SOCK_STREAM är likadan struktur som vid filhantering. Övriga värden se inkluderingsfilen sys/socket.h

• protokoll symbolisk heltalsvärde betecknar uttagets sk. protokollfamilj • 0 UNIX väljer • PF_UNSPEC ospecificerad • PF_UNIX samma UNIX- dator • PF_INET TCP/IP- nät • Övriga värden se inkluderingsfilen sys/socket.h

OBS! Synkroniserade par read – write förutsätter typ =SOCK_STREAM Returnerar:

• Uttagsdeskriptor (heltal > 0) • -1 vid misslyckande

Systemanropet bind bind (sd. adress, längd);

• sd uttagsdeskriptor, som socket har returnerat. • adress pekare på en post som innehåller serverprocessens adress

information • längd storleken (antal byte) hos den post som adress pekar på.

Returnerar: • 0 vid framgång • -1 vid misslyckande

Systemanropet listen listen(sd, kölängd);

• sd uttagsdeskriptor, som socket har returnerat. • kölängd maximal kölängd (antal platser i kön) bör vara ≥ 1

Systemanropet accept int accept(sd, adress, &längd);

• sd uttagsdeskriptor, som socket har returnerat. • adress pekare på en post till vilken klientens adress information kopieras. • längd adressen till en heltals variabel som innehåller storleken på den post

som adress pekar på (antal byte, heltalsvariabeln skall initialiseras till detta värde).

Page 34: Process- programmering

Processprogrammering

Sida 34/38

Returnerar: • ett nytt datakanaldeskriptorvärde vid framgång • -1 vid misslyckande

Systemanropet connect Synkroniserar accept connect( sd, adress, längd);

• sd uttagsdeskriptor, som socket har returnerat. • adress pekare på post som innehåller serverprocessens adress information. • längd storlek (antal byte) på den post som adress pekar på.

Systemanropet shutdown shutdown( sd, mode);

• sd uttagsdeskriptor, som socket har returnerat. • mode

• mode=0 inkommande kommunikations avstängs. • mode=1 utgående kommunikations avstängs. • mode=2 all kommunikations avstängs

Returnerar: • Själva uttagsdeskriptorn

Förbindelsen till inkopplad datakana l avbryts med systemanropet close(uttagsdeskriptor);

Kommunikation på samma dator Adressinfo sparas i posten av typen struct sockaddr { u_short sa_family; /* adress familj */ char sa_data[14]; /* tecken tabell för namn */ }; struct sockaddr deklareras i inkluderingsfilen sys/socket.h. I as_family sparas samma värde som i socket() finns som argument (AF_UNIX). I sa_data sparas namnet på sett sk. Datakanal-objekt, som skall vara ett nytt datakanal-objekt i angiven, LOCAL katalog (jfr. Named -pipe).

Page 35: Process- programmering

Processprogrammering

Sida 35/38

Server process ------------------ int sd,ns,len; struct sockaddr serv,cli; len=sizeof(cli); /* initialisering */ sd=socket(AF_UNIX,SOCK_STREAM,0); serv.sa_family=AF_UNIX; unlink(”/tmp/sockname”); /* radering */ strcpy(serv.sa_data,”/tmp/sockname”); bind(sd, &serv,sizeof(serv)); listen(sd,3); while(1) { ns=accept(sd,&cli,&len); if(!fork()) { close(sd); /* kommunikation via ns */ shutdown(ns,2); close(ns); exit(0); } close(ns); } Ett s.k. datakanalobjekt med namnet ”sockname” skapas i ”/tmp”. Ett eventuellt redan existerande objekt raderas först med unlink. Serverprocessen skapar för varje kommunicerande klient en barnprocess som kommunicerar med en accepterad klientprocess. Serverprocessen upprepar accept för att ta emot eventuella nya klienter. Klientprocessen ----------------------- int sd; struct sockaddr serv; sd=socket(AF_UNIX,SOCK_STREAM,0); serv.sa_family=AF_UNIX; strcpy(ser.sa_data,”/tmp/sockname”); connect(sd,&serv,sizeof(serv)); ----------------------------- /* kommunikation via sd */ ------------------------------ shutdown(sd,2); close(sd); Uttagsdeskriptorn används som fildeskriptor i read och write. OBS! Spara helst uttags -objekt i en lokal katalog inte i en nätkatalog.

Page 36: Process- programmering

Processprogrammering

Sida 36/38

Kommunikation via TCP/IP –nät Post för adressinfo: (inkluderingsfil netinet/in.h) struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; };

• sin_family adressfamilj (samma som socket, AF_INET) • sin_port nummer på ingångsport (heltal >0). Undvik portnummer i

/etc/services (färdiga tjänster) • sin_zero bör nollas • in_addr deklareras i netinet/in.h

struct in_addr { ulong s_addr; }; (IP-nummer)

Hantering av IP-nummer/internetnamn Funktionen: unsigned long inet_addr(char *cp); Returnerar:

• IP-nummret för teckensträng i punktformat i cp. • (unsigned long) (-1) vid misslyckande.

Ex. unsigned long addr; addr=inet_addr(”193.167.32.5”); inet_addr deklareras i inkluderingsfilen arpa/inet.h och returnerar (unsigned long) (-1) vid misslyckande. Erhållet värde kan inkopieras ifall struct sockaddr_in serv, kan vi använda: bcopy(&addr,&serv.sin_addr,sizeof(addr)); Även datorns lokala namn eller Internet –namn kan användas med funktionen struct hostent *gethostbyname(char *name); Denna funktion och posttypen struct hostent deklareras i inkluderingsfilen netdb.h struct hostent innehåller bla.

• h_addr pekare på uträknat IP-nummer • h_length antal byte i IP-nummer

Internet namn struct sockaddr_in serv; struct hostent *addr; addr=gethostbyname(”penti.sit.fi”); bcopy(addr->h_addr,&serv.sin_addr,addr->h_length);

Page 37: Process- programmering

Processprogrammering

Sida 37/38

Server process #define PORT (ushort) 13760 int sd,ns,len; struct sockaddr_in serv,cli; len= sizeof(cli); sd=socket(AF_INET,SOCK_STREAM,0); bzero(&serv,sizeof(serv)); serv.sin_port=htons(PORT); serv.sin_family=AF_INET; serv.sin_addr.s_addr=htonl(INADDR_ANY); /* varje IP-nummer för klient duger */ bind(sd,&serv,sizeof(serv)); listen(sd,3); while(1) { ns=accept(sd,&cli,&len); if(!fork())

{ close(sd); /* kommunikation ns */ shutdown(ns,2);

close(ns); exit(0);

} close(ns); } portnummer: 13760 htons,htonl: konverteringsmakron INADDR_ANY: deklareras i netinet/in.h Klient process #define PORT (ushort) 13760 /* samma som i servern */ int sd; unsigned long addr; struct sockaddr_in serv; sd=socket(AF_INET,SOCK_STREAM,0); bzero(&serv,sizeof(serv)); serv.sin_port=htons(PORT); serv.sin_family=AF_INET; addr=inet_addr(”193.167.33.237”); bcopy(&addr,&serv.sin_addr,sizeof(addr)); connect(sd,&serv,sizeof(serv)); /* Kommunikation via sd */ shutdown(sd,2); close(sd); Ifall serverns Internet -namn används:

Page 38: Process- programmering

Processprogrammering

Sida 38/38

• Ersätt unsigned long addr med struct hostent *addr; • Ersätt anrop av inet_addr med addr= gethostbyname(”penti.sit.fi”); • Ersätt bcopy med bcopy (addr->h_addr,&serv.sin_addr,addr->h_length);