Möte 9: Relationer mellan körande processer - (PI)

Relevanta dokument
Grundprogrammen. combine

Möte 7: Uppföljning av föreläsningen med Peer Instruction - (PI)

(2) Skriv ett program som skapar ett antal processer vars relationer beskrivs av nedanstående tidsdiagram a

HI1025 Operativsystem, KTH Haninge, VT2012

... Funktionsanrop. Vad händer när man kör ett program?

Del II: Systemprogrammering och Inter-Process Communication.

Vad händer när man kör ett program? Program och processer. Funktionsanrop. Avsluta programmet

2... uppvisa förmåga att skapa och/eller hantera flerprocessiga program där de ingående processerna ges

Möte 10: Kommunikation mellan processer - (PI)

Om pekare och minneshantering i C, relaterat till operativsystem och särskilt konstruktionen fork() execvp().

read Systemanrop i UNIX Exempel med read & write write int antal_tkn, fd, count; char buffer[size]; antal_tkn = read(fd, buffer, count);

Introduktion till processer

HI1024, Programmering, grundkurs, 8hp KTH STH TENTAMEN. HI1024:TEN2 - Praktisk tentamen Tid: Fredagen den 21 oktober 2011,

printenv sort pager printenv grep args sort pager

Användbara systemanrop och biblioteksfunktioner. 2G1520 Operativsystem

Deluppgift 17 Processhantering: exec, sleep, exit, plist

Raspberry Pi och Tellstick, ett program i C.

Programmeringsteknik med C och Matlab

Övning från förra gången: readword

Föreläsning 7 Strängar

Dagens föreläsning. Specialtecken. Mer om printf. Formateringssträngar. Mer om scanf. Programmeringsteknik för Ingenjörer VT05

Planering Programmering grundkurs HI1024 HT TIDAA

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

Övningsuppgifter till föreläsning 2 Variabler och uttryck

Programmering, grundkurs, 8.0 hp HI1024, omtentamen, TEN1. Tisdagen den 7 juni 2011,

Terminal vad det är vad man kan göra med den

TDIU01 - Programmering i C++, grundkurs

Guido van Robot och olika UNIX-kommandon

KTH STH TENTAMEN. HI1024:TEN2 - Praktisk tentamen Tid: 8-13, den 18 februari 2012

Programmering, grundkurs, 8.0 hp HI1024, HI1900 etc., Tentamen TEN1. Måndagen den 10 januari 2011,

Planering Programmering grundkurs HI1024 HT data

Generell säkerhet. Loggning - Hur mycket ska man logga? Inloggningsrutinerna i Unix. Loggning fortsättning

Introduktionslaboration

Tillämpad UNIX. Laborations-PM Christian von Schultz, Programpaket och processhantering

#include <pthread.h> #include <stdio.h> int p1[2]; void* char_print (void* parameter) { int fds; fds = *((int *)parameter); int i;

Introduktionslaboration

Pascal... Pascal. Pascal... Pascal...

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

Programmering, grundkurs, 8.0 hp HI1024, TEN1. Fredagen den 2 mars 2012

Vem är vem på kursen. Objektorienterad programvaruutveckling GU (DIT011) Kursbok Cay Horstmann: Big Java 3rd edition.

Uppgift 1a (Aktiekurser utan poster)

Uppgift 1 (grundläggande konstruktioner)

Tellstick-15.c. Kompilering av programmet: gcc -o tellstick-15 -Wall -ltelldus-core -W -O2 -s -pipe -lm tellstick-15.c

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Uppgifter till praktiska tentan, del A. (7 / 27)

Pekare och arrayer. Indexering och avreferering

Programmeringsteknik med C och Matlab

En kort text om programmering i C.

C-programmering, föreläsning 1 Jesper Wilhelmsson

Filer och structer Del 2

Olika shell. Skalprogrammering. Pipor och omdirigering av strömmar

Programmering, grundkurs, 8.0 hp HI1024, extra tentamen, TEN1, för TIDAA1. Fredagen den 11 mars 2011,

Boken?!?! Vad är ett program? Kompilerande-Interpreterande Programmeringsmiljö Hello World! Att programmera och ett enkelt program Variabler printf

Loopar och datatyper. Föreläsning 3

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Programmering i C, 7,5 hp

Information Coding / Computer Graphics, ISY, LiTH. Compute shaders!! Framtiden för GPU computing eller sen efterapning av Direct Compute?

C-programmering, föreläsning 2 Jesper Wilhelmsson

lex källkod lex.l lexkompilator lex.yy.c C- kompilator lex.yy.c a.out sekvens av tokens a.out input specifikation av tokens mha reguljära uttryck

Loopar och datatyper. Föreläsning 3

Introduktion till programmering, hösten 2011

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Strängar. Strängar (forts.)

Operativsystem. Innehåll. Operativsystemets funktion. Vad är ett OS? Vart hittar men ett OS? OS hanterar processorns resurser

HI1024 Programmering, grundkurs TEN

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

emopluppen Användning av "Ant" Niklas Backlund Version: 1.4 ( 2002/04/26 07:27:52 UTC)

C++ Funktioner 1. int summa( int a, int b) //funktionshuvud { return a+b; //funktionskropp } Värmdö Gymnasium Programmering B ++ Datainstitutionen

Generell säkerhet. Loggning - Hur mycket ska man logga? Inloggningsrutinerna i Unix. Loggning fortsättning

Systemnära programmering Tentamen. Systemnära programmering, 7.5hp 5 november 2012

Objektorienterad Programmering (TDDC77)

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

BASH. Bourne-Again SHell. Eric Elfving Institutionen för datavetenskap (IDA)

Övningar för del I av kursen

Programmering i C++ Kompilering från kommandoraden

Recap Mera om nya typer Kort Fält. Programmering. Sommarkurs Verónica Gaspes. IDE-sektionen.

Uttryck, satser och strömhantering

Programutveckling med Java Development Kit. (JDK 1.1.x) och Programmers File Editor (PFE 7.02)

Föreläsning 6 pekare och pekare tillsammans med arrayer

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Programmering: att instruera en maskin att utföra en uppgift, kräver olika språk:

Metoder. Inledande programmering med C# (1DV402)

Exempelsamling Assemblerprogrammering

Operativsystem (ID2200/06) XX XX:00-XX:00

Emacs. Eric Elfving Institutionen för datavetenskap (IDA) 22 augusti 2016

Tentamen i Grundläggande Programvaruutveckling, TDA548

Övning Installation av Gentoo och/eller Arch Linux

Lösningar till uppgifterna sätts ut på kurssidan på nätet i dag kl Omtentamen i Programmering C, Fri, Kväll,

Datorer och datoranvändning Föreläsningar 2014/15. Föreläsning 1 Unix. Operativsystem. Unix

Föreläsning 3. Programmering, C och programmeringsmiljö

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

UPPGIFT 1 LAMELLER. Minsta antalet hål: 1. Första lamellen? Andra lamellen? Minsta antalet hål: 3

Tentamen i Introduktion till programmering

PC-teknik, 5 p LABORATION ASSEMBLERINTRODUKTION

Planering Programmering grundkurs HI1024 HT 2014

Sed och Awk. Linuxadministration II 1DV421. Monday, August 8, 11

*Pekarvärden *Pekarvariabler & *

Introduktion Schenker-BTL AB, Stab IT Beskrivning över informationsintegreringmed Schenker, metodbeskrivning version 1.

Kapitel 12. Mer om program Att rapportera buggar och problem make

Java: Utvecklingsverktyg, datatyper, kontrollstrukturer

Transkript:

Möte 9: Relationer mellan körande processer - (PI) Målet med att köra flera processer är ofta att få dem att samverka. Vi ska idag studera olika sätt att får processer att samverka. En viktig form av samverkan är kommunikation man kan lätt skicka strängar till ett körande C-program via kommandoradsparametrarna, man skriver $./a.out kalle lisa olle till programmet som ser ut så här: int main(int argc, char *argv[]) int i; for(i=0;i<argc;i++)printf("%s ", argv[i]); printf("\n\n"); så skriver detta program ut parametrarna som också inkluderar programnamnet. Vi får körningen som, förvirrande nog, ser ut exakt likadant som anropet (så när som på att prompten, $ saknas):./a.out kalle lisa olle Vi ska nu börja studera relationer mellan körande processer. Vi har tidigare sett så kallade pipar, alltså att man skriver till exempel ls -l grep Johnny så kör vi ls -l-kommandot (och lista filer) och skicar resultatet till kommandot grep Johnny som skriver ut de rader som innehåller texten Johnny. Det här är ett vanligt sätt att kombinera processer i UNIX och vi ska se i detalj på vad som händer och även koppla ihop det med den tidigare teorin om processer. Processer har någonting som heter standard in och standard out (och även standard error, men vi väntar med det). Detta är så kallade strömmar och så fort en process skapas så har den per default de tre strömmarna som är nämnda här. På strömmen standard in kommer det data in till den körande procssen och standard out och standard error är två utströmmar, men vi ska bara befattar oss med standard in och standard out än så länge. I exemplet ovan med ls -l som listade filer och grep Johnny som skrev ut de rader som innehåller texten Johnny så skapades två processer och de kopplades ihop via en pipe en rörledning, som tog det som kom på standard out från ls -l och skickade det till standard in på processen grep Johnny. Strömmar har också en siffra (som vi senare ska kalla fildeskriptor) och standard out har 1 och standard in har 0. Med hjälp av lågnivåkommandona read() och write() kan vi skriva och läsa till standard in och standard out precis som med printf() och scanf() fast utan buffrar och formatering. Om vi nöjer oss med att skicka heltal så kan vi studera de enkla programmen out.c och showp.c (som vi kompilerar till out och showp): out.c showp.c int a=atoi(argv[1]); write(1, &a, sizeof(int)); int a; read(0,&a,sizeof(int)); printf("%d\n", a); system("ps -o pid,ppid,pgid,sid,comm"); johnnyp@kth.se 1(6)

Programmet out tar en kommandoradsparameter och skickar på sin standard out. Det är det enda den gör, den fungerar som ett slags start för de program vi ska studera senare. Programmet showp fungerar som slutpunkten som skriver ut ett resultat och visar de körande processerna med systemanropet ps. Om vi bara kombinerar dessa båda program i en pipe så ser resultatet ut så här: $./out 20./showp 20 5050 4687 5050 4687 out 5051 4687 5050 4687 showp 5052 5051 5050 4687 ps Vi tolkar resultatet så här: programmet out fick 20 som kommandoradsparameter. Det skickades iväg på standard out som via pipen kom in till showp. Det programmet, i sin tur, läste det från sin standard in och skrev ut det. Det första vi ser är alltså utskrift av talet 20. Därefter körde showp systemanropet ps som beskrev hela sitauationen, vi ser vårt skal (bash) som tydligen har processid 4687, och de båda programmen out och showp som har processid 5050 respektive 5051. Slutligen ser vi också processid för ps som är 5052. Vi ser att skalet är förälder till out respektive showp medan showp själv är förälder till ps. Vi skapar nu ett till program som heter double som dubblerar det den får in och skickar vidare resultatet. Vi skriver det så här: int a; read(0,&a,sizeof(int)); a=2*a; write(1,&a,sizeof(int)); och om vi kombinerar detta med de tidigare programmen i pipen $./out 20./double./showp så kan vi få körningen 40 5066 4687 5066 4687 out 5067 4687 5066 4687 double 5068 4687 5066 4687 showp 5069 5068 5066 4687 ps Och detta kan tolkas som ovan, fast nu har vi ytterligare en spelare med som heter double som, ja dubblerar det som skrivs ut innan utskriften sker. Det intressanta börjar när vi skriver lite mer komplicerade program som också skapar egna processer. Vi ska börja med att ta bort utskriften i showp och vi ska inte längre påverka talet som vi johnnyp@kth.se 2(6)

skickar genom att dubblera osv, vi ska skicka processid:n och skapa barnprocesser och se vad som händer. Vår nya showp ser då ut så här: system("ps -o pid,ppid,pgid,sid,comm"); Alltså bara ett anrop av ps. Vi börjar med att skriva ett program som heter spawn som tar in ett heltal och skapar så många barnprocesser: int i,n; for(i=0;i<n;i++) sleep(30); exit(0); Om vi nu kör./out 3./spawn./showp så får vi ett resultat av typen: 5169 4687 5169 4687 out 5170 4687 5169 4687 spawn 5171 4687 5169 4687 showp 5172 5171 5169 4687 ps 5173 5170 5169 4687 spawn 5174 5170 5169 4687 spawn 5175 5170 5169 4687 spawn Vi ser här de tre barnprocesserna. Om vi nu, direkt igen kör samma anrop, alltså vi ger återigen kommandot./out 3./spawn./showp så kan resultatet se ut så här: 5173 1 5169 4687 spawn 5174 1 5169 4687 spawn 5175 1 5169 4687 spawn 5176 4687 5176 4687 out 5177 4687 5176 4687 spawn 5178 4687 5176 4687 showp 5179 5178 5176 4687 ps 5180 5177 5176 4687 spawn 5181 5177 5176 4687 spawn 5182 5177 5176 4687 spawn Varför det? johnnyp@kth.se 3(6)

PI-fråga: Eftersom processer som lever men vars föräldrar dör adopteras av init (med processid 1) så kan vi ordna så att en barnprocess omedelbart adopteras av init genom att låta en barnprocess dö efter den skapat ytterligare en barnprocess, alltså ett barnbarn som då alltså ska adopteras av init. Vi skriver om spawn och kallar den spawntoinit enligt denna princip. Vi vill alltså ha en körning av typen $./spawntoinit./showp 5225 4687 5225 4687 spawntoinit 5226 4687 5225 4687 showp 5228 5226 5225 4687 ps 5229 1 5225 4687 spawntoinit Vilken av nedanstående varianter av är korrekt? A. if(fork()!=0) sleep(30); exit(0); C. sleep(30); exit(0); wait(0); B. sleep(30); exit(0); D. if(fork()!=0) sleep(30); exit(0); johnnyp@kth.se 4(6)

Vi utökar vår arsenal av små program som gör roliga saker med processer med ett program som dödar en utvald process. Vi skriver det så här: int pid; read(0, &pid, sizeof(int)); kill( pid, 9 ); Programmet läser alltså först in ett tal, ett processid, och dödar den process som har det processid:t. Vi modifierar spawn så att den skapar ett antal processer och skickar processid:t på en av barnprocesserna vidare, det är den barnprocessen som dödas av killp. Den första nya versionen av spawn kallar vi spawn2 och den ser ut så här: int i,n,half, killp; pid_t pid; half = n/2; for(i=0;i<n;i++) pid=fork(); if(pid==0)sleep(30); exit(0); if(i==half)killp=pid; write(1,&killp,sizeof(int)); När vi nu ger kommandot./out 6./spawn2./killp./showp så får vi resultatet 5463 4687 5463 4687 out 5464 4687 5463 4687 spawn2 5465 4687 5463 4687 killp 5466 4687 5463 4687 showp 5467 5464 5463 4687 spawn2 5468 5464 5463 4687 spawn2 5469 5464 5463 4687 spawn2 5470 5464 5463 4687 spawn2 <defunct> 5471 5466 5463 4687 ps 5472 5464 5463 4687 spawn2 5473 5464 5463 4687 spawn2 Vi får alltså en zombie... hur kan vi undvika det? Är det något problem att ps har PID mitt i? johnnyp@kth.se 5(6)

PI-fråga: Vi vill kombinera de två tidigare momenten och skicka alla barnprocesser utom en till init och döda den vi inte skickar till init, hur gör vi detta? Vi baserar oss på den vanliga killp men hur ska spawn skrivas? Om vi kör./out 6./spawn3./killp./showp så vill vi ha resultatet 4111 4105 4111 4111 bash 4211 4111 4211 4111 out 4212 4111 4211 4111 spawn3 4213 4111 4211 4111 killp 4214 4111 4211 4111 showp 4219 4214 4211 4111 ps 4221 1 4211 4111 spawn3 4223 1 4211 4111 spawn3 4224 1 4211 4111 spawn3 4225 1 4211 4111 spawn3 4226 1 4211 4111 spawn3 Vilken är den korrekta versionen av spawn3.c? A. int i,n, killp; pid_t pid; for(i=0;i<n-1;i++) pid = fork(); if(pid==0) sleep(30); exit(0); killp = fork(); if(killp==0) sleep(30); exit(0); write(1,&killp,sizeof(int)); for(i=0;i<n;i++)wait(0); C. Båda är korrekta. B. int i,n, killp; pid_t pid; killp = fork(); if(killp==0) sleep(30); exit(0); write(1,&killp,sizeof(int)); for(i=0;i<n-1;i++) pid = fork(); if(pid==0) sleep(30); exit(0); for(i=0;i<n;i++)wait(0); D. Ingen är korrekt. johnnyp@kth.se 6(6)