Documente Academic
Documente Profesional
Documente Cultură
Rezultatul rularii:
0.
1.
2.
0.
3.
1.
4.
2.
5.
3.
6.
4.
7.
5.
8.
6.
9.
7.
8.
9.
#include<unistd.h>
main() {
printf("Urmeaza rezultatul executiei comenzii ls:\n");
execl("/bin/ls", "/bin/ls", "-l", NULL);
//execl("/bin/ls","/bin/ls","-l","execl.c", "fork1.c", "xx", NULL);
//execl("/bin/ls","/bin/ls","-l","*.c", NULL);
printf("Aici nu se ajunge decat in urma unei erori exec\n");
}
Sursa execlp.c:
#include<stdio.h>
#include<unistd.h>
main() {
printf("Urmeaza rezultatul executiei comenzii ls:\n");
execlp("ls", "ls", "-l", NULL) == -1;
printf("Aici nu se ajunge decat in urma unei erori exec\n");
//
if (execlp("ls","ls","-l",NULL) == -1) {
//
printf("Aici nu se ajunge decat in urma unei erori exec\n");
//
perror("Aici se impune un mesaj explicativ; sistemul raspunde");
//
}
}
Sursa execv.c:
#include<stdio.h>
#include<unistd.h>
main() {
char* argv[3];
argv[0] = "/bin/ls";
argv[1] = "-l";
argv[2] = NULL;
printf("Urmeaza rezultatul executiei comenzii ls:\n");
execv("/bin/ls",argv);
printf("Aici nu se ajunge decat in urma unei erori exec\n");
}
Efectul oricaruia dintre programele de mai sus este:
Urmeaza rezultatul executiei comenzii ls:
total 184
-rwxr-xr-x 1 florin florin 7176 2011-03-17
-rwxrwxrwx 1 florin florin 340 2011-03-17
-rwxrwxrwx 1 florin florin 404 2011-03-17
-rwxrwxrwx 1 florin florin 370 2011-03-17
-rwxrwxrwx 1 florin florin 364 2011-03-17
-rw-r--r-- 1 florin florin 353 2011-03-17
-rw-r--r-- 1 florin florin 386 2011-03-17
16:47
16:43
16:43
16:43
15:45
16:06
16:10
a.out
execl.c
execlp.c
execv.c
fork1.c
fork2.c
fork3.c
1.
Primul program foloseste excl. De aceea comanda se specifica
cu calea completa /bin/ls. Urmeaza lista argumentelor din
linia de comanda (de aceea apare dublarea primului argument).
Al doilea foloseste exclp, deci comanda este cautata in
directoarele din PATH, de aceea se specifica doar ls.
Al treilea foloseste execv. La fel ca primul, specifica
calea absoluta. Acest program pregateste in prelabil un
tablou cu trei pointeri la stringuri in care se pun cele
doua argumente ale liniei de comanda si pointerul NULL
ce marcheaza sfarsitul tabloului. Compilatorul in mod
automat aloca spatiu de memorie pentru fiecare constanta
string. In urma atribuirilor a[0] = --- si a[1] = --se atribuie adresele stringurilor respective.
Daca este cazul, un astfel de tablou se poate aloca dinamic
n2 = atoi(argv[i+1]); // si la nenumeric
if (n1 == 0 || n2 == 0) exit(2);
if ((n1 + n2) % 2 == 0) exit(0);
else
exit(1);
// Aici se termina fiecare fiu
}
}
// Parintele asteapta terminarile fiilor
for (i = 1; i < argc-1; i += 2) {
wait(&n1);
switch (WEXITSTATUS(n1)) {
case 0: pare++;break;
case 1: impare++;break;
default: nenum++;
}
}
printf("Pare %d, impare %d, nenumerice %d\n",pare, impare, nenum);
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include <sys/wait.h>
main(int argc, char* argv[]) {
char com[200];
strcpy(com, "gcc -o ceva "); // fabricat comanda
strcat(com, argv[1]);
if (WEXITSTATUS(system(com)) == 0)
execl("./ceva","./ceva", NULL);
printf("Erori de compilare\n");
}
Compilarea lui se face
gcc -o comprun compilerun.c
Executia se face, de exemplu, prin
./comprun fork1.c
Ca efect, daca compilarea sursei argument (fork1.c) este corecta,
atunci compilatorul gcc creeaza fisierul ceva si intoarce
cod de retur o, dupa ceva este lansat prin execl.
Daca esueaza compilarea, se va tipari doar mesajul.
Sursa Python echivalenta:
compilerun.py
------------import sys
import os
com = "gcc -o ceva "+sys.argv[1]
if os.WEXITSTATUS(os.system(com)) == 0:
os.execl("./ceva","./ceva")
print "Erori de compilare"
Exemplul 5: Prelucrarea simultana a mai multor fisiere text.
-----------------------------------------------------------Dorim sa transformam un fisier text intr-un alt fisier text,
cu acelasi continut, dar in care toate cuvintele din el sa
inceapa cu litera mare.
Un astfel de program va fi apelat:
capitalizare fisierintrare fisieriesire
Ne propunem sa prelucram simultan mai multe astfel de fisiere.
De aceea vom creea un proces master, care primeste la linia
de comanda numele fisierelor al caror continut va fi capitalizat:
master fisier1 fisier2 - - - fisiern
Rezultatul va consta din fisierele:
fisier1.CAPIT, fisier2.CAPIT, - - - fisiern.CAPIT
Procesul master va crea n procese fii, iar fiecare fiu i va lansa
prin execl programul:
capitalizare fisi fisi.CAPIT
Sursa capitalizare.c este:
#include<stdio.h>
#include<string.h>
-------
typedef struct {
int lung;
int i;
char s[MAXS];
} Mesaj;
#define PLUS (sizeof(int))
Citirea / scrierea unui Mesaj la comunicarea prin pipe sau
FIFO se face in doua etape:
1. Se scrie / citeste lung.
2. Se fac scrieri / citiri repetate, pana cand sunt
schimbati toti octetii continutului mesajului.
De ce a fost necesara o astfel de abordare?
Din cauza functionarii apelurilor sistem read si write.
Aceste apeluri sunt atomice, insa nu asigura schimbul
numarului total de octeti solicitati (al treilea argument
al apelurilor read si write). Aceste apeluri intorc, la
sfarsit, numarul de octeti efectiv schimbati.
Din aceasta cauza este dificila comunicarea prin pipe sau
FIFO intre mai mult de doua procese: procesele care citesc
nu stiu de la ce procese cititoare isi preia octetii!
Pentru implementarea schimbului de mesaje sunt folosite
functiile Read, Write, ReadMes, WriteMes.
---- ----- ------- -------Primele doua aplica repetat apeluri read, write
pana la schimbarea a exact n octeti, n parametru de intrare.
ReadMes si WriteMes schimba mai intai lungimea continutului,
dupa care cere schimbul complet al acestuia.
Cele patru functii sunt prezentate in sursa ReadWrite.c
----------void Read(int f, char *t, int n) {
char *p;
int i, c;
for (p=t, c=n; ; ) {
i = read(f, p, c);
if (i == c) return;
c -= i;
p += i;
}
}
void Write(int f, char *t, int n) {
char *p;
int i, c;
for (p=t, c=n; c; ) {
i = write(f, p, c);
if (i == c) return;
c -= i;
p += i;
}
}
Mesaj *ReadMes(int canal) {
static Mesaj mesaj;
read(canal, (char*)&mesaj.lung, sizeof(int));
Read(canal, (char*)&mesaj+sizeof(int), mesaj.lung);
return &mesaj;
}
void WriteMes(int canal, Mesaj *pm) {
write(canal, (char*)pm, sizeof(int));
Write(canal, (char*)pm+sizeof(int), pm->lung);
}
Actiunea principala a serverului este dirijata de functia
void parinte(int in, in out)
------Parametrii sunt handle ale canalelor prin care citeste mesaje
de la clienti, respectiv scrie raspunsurile spre clienti.
Dupa caz, aceste handle pot fi descriptori pipe, descriptori
FIFO, sau, cum vom vedea in laboratoarele viitoare,
descriptori de memorie partajata sau de cozi de mesaje.
Actiunea acestei functii este simpla: citeste in mod repetat
cate un mesaj de la un client, apeleaza dir (sau dirPopen),
dupa care scrie in mesaj raspunsul pentru client.
Sursa parinte.c este:
--------void parinte(int in, int out) {
Mesaj *pm;
for ( ; ; ) {
pm = ReadMes(in);
//pm = dirPopen(pm->i, pm->s);
pm = dir(pm->i, pm->s);
WriteMes(out, pm);
}
}
Actiunea principala a clientului este dirijata de functia
void fiu(int in, in out)
--La fel ca la server, parametrii sunt handle ale canalelor
prin care citeste mesaje de la server, respectiv scrie
cereri catre server.
Dupa caz, aceste handle pot fi descriptori pipe, descriptori
FIFO, sau, cum vom vedea in laboratoarele viitoare,
descriptori de memorie partajata sau de cozi de mesaje.
Clientul citeste in mod repetat de la intrarea standard
cate un numar l si un string s.
Dupa fiecare citire prepara un mesaj, pe care il trimite
la server.
Apoi citeste mesajul de raspuns primit de la server si il
listeaza pe iesirea standard.
Sursa fiu.c descrie actiunea clientului:
----void fiu(int in, int out) {
Mesaj *pm, mesaj;
char *pc,linie[MAXL];
int i;
for ( ; ; ) {
printf("Dati: numar|sufix: ");
pc = (char*)fgets(linie, MAXL, stdin);
if (pc == NULL) break;
linie[strlen(linie)-1] = '\0';
pc = strstr(linie, "|");
$ mkfifo fifo2
Inainte de aceasta, daca aceste FIFO-uri deja exista, ele se
sterg cu:
$ rm fifo1
$ rm fifo2
Deoarece si clientul si serverul sunt ai aceluiasi user, am
preferat ca cele doua FIFO-uri sa se afle in directorul curent.
Daca cele doua procese apartin la useri diferiti, atunci
este convenabil ca FIFO-urile sa fie /tmp/fifo1 si /tmp/fifo2.
Sursa serverului este fifos.c:
-------#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "mesaj.h"
#include "ReadWrite.c"
#include "dir.c"
#include "parinte.c"
main() {
int f1, f2;
fclose(stdin);
fclose(stdout);
f1 = open("fifo1", O_WRONLY);
f2 = open("fifo2", O_RDONLY);
parinte(f2, f1);
}
Sursa clientului este fifoc.c:
------#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include "mesaj.h"
#include "ReadWrite.c"
#include "fiu.c"
main() {
int f1, f2;
f1 = open("fifo1", O_RDONLY);
f2 = open("fifo2", O_WRONLY);
fiu(f1, f2);
close(f1);
close(f2);
}
Iata cateva executii cu popen sau fara, cu pipe sau FIFO
--------------florin@florin-laptop:~/probleme/UPipe-H$ #dir
florin@florin-laptop:~/probleme/UPipe-H$ gcc pipe.c
florin@florin-laptop:~/probleme/UPipe-H$ ./a.out
Dati: numar|sufix: 5|.c
47
4 fiu.c
10 ReadWrite.c
22 parinte.c
32 fifos.c
40 pipe.c
Dati: numar|sufix: ^C
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
Dati: numar|sufix: 5|.c
43
4 fifoc.c
12 fifos.c
20 fiu.c
26 parinte.c
36 pipe.c
Dati: numar|sufix: ^C
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
[1] 2066
florin@florin-laptop:~/probleme/UPipe-H$
Dati: numar|sufix: 5|.c
43
4 fifoc.c
12 fifos.c
20 fiu.c
26 parinte.c
36 pipe.c
Dati: numar|sufix: ^C
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
[1]+ Terminated
./s
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
florin@florin-laptop:~/probleme/UPipe-H$
[1] 2142
florin@florin-laptop:~/probleme/UPipe-H$
Dati: numar|sufix: 5|.c
47
4 fiu.c
10 ReadWrite.c
22 parinte.c
32 fifos.c
40 pipe.c
Dati: numar|sufix:
#dirPopen
gcc pipe.c
./a.out
mkfifo fifo1
mkfifo fifo2
#dirPopen
gcc -o s fifos.c
gcc -o c fifoc.c
./s&
./c
#dir
kill 2066
rm fifo1
rm fifo2
mkfifo fifo1
mkfifo fifo2
gcc -o s fifos.c
gcc -o c fifoc.c
./s&
./c
def __str__(self):
ser = ""
for l in self.s:
ser += l+"|"
ser = ser[:-1]
ser = self.i2s(self.lung)+self.i2s(self.i)+ser
return ser
def i2s(self, i):
sir = "000000000000000000"+`i`
if sir.endswith("L"): sir = sir[:-1]
return sir[-self.SIZEOFINT:]
dir.py
-----import os
import Mesaj
def dir(l, s):
mesaj = Mesaj.Mesaj(None)
mesaj.s = []
lung = 0
i = 1
for linie in os.listdir("."):
if i > l: break
if lung + len(linie) + len(mesaj.s) > mesaj.MAXS: break
if len(linie) < len(s): continue
if linie[len(linie)- len(s):] != s: continue
mesaj.s += [linie]
i += 1
lung += len(linie)
mesaj.lung = mesaj.PLUS + lung + len(mesaj.s) - 1
if len(mesaj.s) == 0: mesaj.lung += 1
return mesaj
def dirPopen(l, s):
mesaj = Mesaj.Mesaj(None)
mesaj.s = []
lung = 0
i = 1
for linie in os.popen("ls -1", "r").readlines():
linie = linie[:-1]
if i > l: break
if lung + len(linie) + len(mesaj.s) > mesaj.MAXS: break
if len(linie) < len(s): continue
if linie[len(linie)- len(s):] != s: continue
mesaj.s += [linie]
i += 1
lung += len(linie)
mesaj.lung = mesaj.PLUS + lung + len(mesaj.s) - 1
if len(mesaj.s) == 0: mesaj.lung += 1
return mesaj
ReadWrite.py
-----------import Mesaj
import os
def Read(f, n):
c = n
sir = ""
while c > 0:
s = os.read(f, c);
sir += s
c -= len(s)
return sir
def Write(f, sir):
c = len(sir)
p = 0
while c > 0:
i = os.write(f, sir[p:])
c -= i
p += i
def ReadMes(canal):
lung = os.read(canal, Mesaj.Mesaj.SIZEOFINT)
ser = Read(canal, int(lung))
return Mesaj.Mesaj(lung+ser)
def WriteMes(canal, mesaj):
lung = mesaj.SIZEOFINT+mesaj.lung
Write(canal, str(mesaj)[:lung])
parinte.py
---------import ReadWrite
import dir
def parinte(iN, out):
while True:
mesaj = ReadWrite.ReadMes(iN)
mesaj = dir.dir(mesaj.i, mesaj.s[0])
#mesaj = dir.dirPopen(mesaj.i, mesaj.s[0])
ReadWrite.WriteMes(out, mesaj)
fiu.py
-----import sys
import Mesaj
import ReadWrite
def fiu(iN, out):
while True:
print "Dati: numar|sufix: ",
linie = sys.stdin.readline()
if not linie: break
linie = linie[:-1]
pc = linie.find("|")
if pc < 0: continue
mesaj = Mesaj.Mesaj(None)
mesaj.s = []
mesaj.i = int(linie[:pc])
mesaj.s += [linie[pc+1:]]
mesaj.lung = mesaj.PLUS + len(mesaj.s[0])
ReadWrite.WriteMes(out, mesaj)
mesaj = ReadWrite.ReadMes(iN)
for l in mesaj.s:
print l
pipe.py
-------
import sys
import os
import parinte
import fiu
def main():
fp = os.pipe()
pf = os.pipe()
pid = os.fork()
if pid < 0: exit(2)
if pid > 0: # Codul serverului (parintelui)
sys.stdin.close()
sys.stdout.close()
os.close(fp[1])
os.close(pf[0])
parinte.parinte(fp[0], pf[1])
else: # Codul clientului (fiului)
os.close(fp[0])
os.close(pf[1])
fiu.fiu(pf[0], fp[1])
os.close(pf[0])
os.close(fp[1])
main()
fifos.py
-------import sys
import os
import parinte
def main():
sys.stdin.close()
sys.stdout.close(
f1 = os.open("fifo1", os.O_WRONLY, 0666)
f2 = os.open("fifo2", os.O_RDONLY, 0666)
parinte.parinte(f2, f1)
main()
fifoc.py
-------import os
import fiu
def main():
f1 = os.open("fifo1", os.O_RDONLY, 0666)
f2 = os.open("fifo2", os.O_WRONLY, 0666)
fiu.fiu(f1, f2)
os.close(f1)
os.close(f2)
main()