Igino Corona

Documenti analoghi
Igino Corona

Gestione dinamica della memoria

Perché il linguaggio C?

Le strutture. Una struttura C è una collezione di variabili di uno o più tipi, raggruppate sotto un nome comune.

File I/O. M. R. Guarracino: File I/O 1

La gestione della memoria dinamica Heap

Il linguaggio C. Puntatori e dintorni

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 3

Uso avanzato dei puntatori Allocazione dinamica della memoria

Digressione: man 2...

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 3. 1 strace : visualizzazione delle system call invocate da un processo

Compendio sottoinsieme del C++ a comune col C. (Libreria standard, Input/Output, Costanti, Dichiarazioni e typedef, Memoria Dinamica)

L'Allocazione Dinamica della Memoria nel linguaggio C

Directory. Le directory unix sono file.

Per operare su un file abbiamo bisogno di aprirlo, scriverlo, leggerlo, chiuderlo:

Le strutture. Una struttura C è una collezione di variabili di uno o più tipi, raggruppate sotto un nome comune.

Esercitazione di Lab. di Sistemi Operativi 1 a.a. 2011/2012

Puntatori. Un puntatore contiene un numero che indica la locazione di memoria dove è presente la variabile puntata

Corso di Fondamenti di Informatica. Puntatori e Allocazione Dinamica

System calls. permettono ai programmi utente di richiedere servizi al Sistema Operativo. servizi come scrittura di file, stampa su video, ecc.

C: panoramica. Violetta Lonati

Laboratorio di Sistemi Operativi

Sistemi Operativi Teledidattico

Scrivere alla fine di un file Vi sono due modi per scrivere alla fine di un file:

Primi passi col linguaggio C

Programmazione di sistema in Linux: gestione dei file. E. Mumolo

Unità Didattica 4 Linguaggio C. Vettori. Puntatori. Funzioni: passaggio di parametri per indirizzo.

Le operazioni di allocazione e deallocazione sono a carico del sistema.

File binari e file di testo

prova.c #include <stdio.h> char funzione(char); codice oggetto del main()

Sistemi Operativi (M. Cesati)

L Allocazione Dinamica della Memoria

Università degli Studi di Cassino Corso di Fondamenti di Informatica Tipi strutturati: Stringhe. Anno Accademico 2010/2011 Francesco Tortorella

Breve Riepilogo del Linguaggio C

Informatica 1 Tipi e dichiarazioni in C++ C++ - Tipi e dichiarazioni 1

Precedenza e associatività. Complementi sul C - 2. Esempi. Esempi

puntatori Lab. Calc. AA 2007/08 1

Laboratorio di Sistemi Operativi primavera 2009

I puntatori e l allocazione dinamica di memoria

Le basi del linguaggio Java

Università degli Studi di Cassino e del Lazio Meridionale Corso di Fondamenti di Informatica Allocazione dinamica di memoria

Chiamate di sistema per la Inter Process Communication (IPC) in POSIX. E.Mumolo, DEEI

Laboratorio di Sistemi Operativi

Lab. di Sistemi Operativi - Esercitazione n 9- -Thread-

Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

I puntatori. Un puntatore è una variabile che contiene l indirizzo di un altra variabile. puntatore

Lezione 19 e Allocazione dinamica della memoria - Direttive al preprocessore - Libreria standard - Gestione delle stringhe

Sulla libreria standard, III. Manipolare file con stdio.h

Processi in Linux. Igino Corona 20 Ottobre 2009

I Processi nel SO UNIX

Progetto II: Il linguaggio C e le chiamate di sistema sui processi

Lezione 21 e 22. Valentina Ciriani ( ) Laboratorio di programmazione. Laboratorio di programmazione. Lezione 21 e 22

Operazioni su file di caratteri

Il File-System. I file in ambiente Linux Stefano Quer Dipartimento di Automatica e Informatica Politecnico di Torino

GESTIONE DEI FILE IN C. Docente: Giorgio Giacinto AA 2008/2009

Addendum alle chiamate di sistema per la gestione processi. E Mumolo

Introduzione ai puntatori

Definizione Allocazione e deallocazione di variabili Allocazione e deallocazione di vettori

Introduzione alla programmazione in linguaggio C

L apertura di un file ci restituisce un puntatore a una struttura chiamata FILE fopen:

Stringhe e allocazione dinamica della memoria

Variabili dinamiche. Obiettivi: Presentare le variabili dinamiche, allocate e deallocate nell area HEAP, e le funzioni malloc e free

Il linguaggio C. Puntatori e dintorni

Lab. di Sistemi Operativi - Esercitazione n 7- -Gestione dei processi Unix-

Capitolo 5 -- Stevens

Processi in Linux. Stru/ura file eseguibili

Comandi. Sistema Operativo

Allocazione Dinamica della Memoria

Preprocessore, linker e libreria standard

I files in C. A cura del prof. Ghezzi

Allocazione dinamica della memoria

Istituto Tecnico Industriale M. M. Milano Polistena. Classe III D a.s. 2015/2016 C++ Guida Base

Il linguaggio C. Puntatori e Array

Funzioni e. Alessandra Giordani Mercoledì 16 maggio 2012

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Corso di Fondamenti di Informatica

Esercizio 1: funzione con valore di ritorno di tipo puntatore

Digressione: man (2)...

Il sistema C è formato dal linguaggio C, dal preprocessore, dal compilatore, dalle librerie e da altri strumenti di supporto.

&& (nessun altro processo ha il file aperto) && (il fd e chiuso) Cancella il file;

Corso di Laboratorio di Sistemi Operativi

Scrivere alla fine di un file Vi sono due modi per scrivere alla fine di un file:

Esercitazione 11. Liste semplici

Corso di Sistemi Operativi Esercitazioni

Appunti del corso di Informatica 1. 6 Introduzione al linguaggio C

Corso di Reti di Calcolatori L-A

DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE. File. Marco D. Santambrogio Ver. aggiornata al 15 Maggio 2013

Strutture Dati Dinamiche

SmallShell Piccolo processore comandi

Dal C al C++ Corso di Linguaggi di Programmazione ad Oggetti 1. a cura di Giancarlo Cherchi

System call per la gestione di processi

Programmazione di base

Allocazione dinamica della memoria

Complementi. - Ridefinizione di tipo - - Costrutto switch - - Programmazione su più file - - Parametri della funzione main - Funzione system -

L ambiente di un processo (I)

Processi UNIX. I Processi nel SO UNIX. Gerarchie di processi UNIX. Modello di processo in UNIX

Input/Output. Lettura e scrittura Caratteri e Stringhe: Terminale e file. Input/output. caratteri stringhe formattato ascii binari

Bloodshed Dev-C++ Bloodshed Dev-C++ è l IDE usato durante le esercitazioni/laboratorio. IDE = Integrated Development Environment. Codice corso: 21012

I/O su Socket TCP: read()

Il processo figlio : utilizza lo stesso codice che sta eseguendo il padre ;

Transcript:

Sistemi Operativi Esercitazione 2: Richiami di programmazione in linguaggio C/C++ Igino Corona igino.corona@diee.unica.it martedi 7 Ottobre 2008

Linguaggi di programmazione Un linguaggio di programmazione è un linguaggio formale tramite il quale vengono espressi e deniti (codice sorgente) i programmi. Dal punto di vista pratico, vi sono due principali tipologie di linguaggi di programmazione: Compilati nei quali il codice sorgente del programma viene processato da un compilatore, che dopo averne vericato la correttezza (in genere sintattica), viene tradotto in un formato (binario) eseguibile dal sistema operativo Interpretati nei quali il codice sorgente del programma viene processato da un interprete che esegue le istruzioni, interagendo col sistema operativo sottostante

Linguaggi di programmazione Il C (C++) è un linguaggio di programmazione compilato. Questo signica che se vogliamo creare un programma tramite C (C++), che sia eseguibile su un certo sistema operativo, dobbiamo avere a disposizione il compilatore specico. Per linux (come per Windows) sono disponibili diversi compilatori C e C++. Nel seguito vedremo i compilatori GNU: gcc (per C) e g++ (per C++).

Linguaggi di programmazione Il C (C++) è un linguaggio di programmazione compilato. Questo signica che se vogliamo creare un programma tramite C (C++), che sia eseguibile su un certo sistema operativo, dobbiamo avere a disposizione il compilatore specico. Per linux (come per Windows) sono disponibili diversi compilatori C e C++. Nel seguito vedremo i compilatori GNU: gcc (per C) e g++ (per C++). Qualche esempio di linguaggio di programmazione interpretato? Tra i più famosi vi sono Java e Python.

Funzioni di libreria statiche e condivise Una funzione è una collezione di istruzioni che permettono di svolgere una determinata operazione e restituire dei valori. Ogni programma fa uso di funzioni, siano esse denite nel programma stesso o (già scritte e) disponibili in librerie. Per libreria si intende un contenitore di funzioni memorizzato in un le in formato codice oggetto. Nei sistemi UNIX, le librerie sono in genere presenti in /usr/lib e /usr/local/lib.

Funzioni di libreria statiche e condivise Una libreria può essere statica: le funzioni referenziate all'interno di un programma vengono estratte dalla libreria e incorporate nel le eseguibile in fase di compilazione (fase di linking) Una libreria può essere condivisa: contiene oggetti che condivisibili da più programmi; i le eseguibili possono contenere solo i riferimenti a tali oggetti, che vengono caricati in memoria (se non già presenti) in fase di esecuzione del programma

Funzioni di libreria statiche e condivise Compilare un programma C in Linux tramite shell Produrre un eseguibile a partire dal codice sorgente C: gcc -o <nome_eseguibile> <nome_sorgente>.c Produrre solo il codice oggetto: gcc -c <nome_sorgente>.c

Funzioni di libreria statiche e condivise Creare una libreria di funzioni Si vuole creare una libreria relativa alle funzioni ascii() e change_case() 1. Creo il codice oggetto relativo alle funzioni: g++ -c ascii.cxx g++ -c change_case.cxx 2. Creo la libreria standard libmy_demo.a, usando ar (UNIX archive utility): ar cr libmy_demo.a ascii.o change_case.o 1 1 ar prevede l'inserimento dei ag (in questo caso cr) senza il trattino...

Funzioni di libreria statiche e condivise Utilizzare la libreria di funzioni creata Creazione dell' header le my_demo.h deve contenere i prototipi delle funzioni ascii() e change_case() Uso della libreria in main.cxx g++ -o main main.cxx -L. -lmy_demo L' opzione -lmy_demo chiede al compilatore di eettuare il link tra il condice oggetto prodotto dalla compilazione di main.cxx e il codice oggetto della libreria libmy_demo.a L' opzione -L. inserisce la directory corrente tra i percorsi in cui il compilatore andrà a cercare libmy_demo.a

Funzioni di libreria statiche e condivise Utilizzare una libreria di funzioni (in generale) Link di librerie gcc -o <nome_eseguibile> <nome_sorgente>.c -l<nome_libreria> -L<PATH_librerie> Il link del codice C scritto dall' utente con le librerie viene eettuato su richiesta L' opzione -l del compilatore viene seguita dal nome della libreria senza il presso lib e l' estensione All' interno del codice sorgente deve essere incluso l' header (es. <math.h>) relativo alla libreria da utilizzare Esempio: g++ -o prgm prgm.cxx -lm Esegue il link della libreria matematica libm.a (oppure.so)

Funzioni di libreria statiche e condivise Librerie standard In genere assieme al compilatore vengono fornite un certo numero di librerie di funzioni predenite (es. librerie per l' input/output, librerie matematiche, etc.) libc è una libreria molto importante che viene utilizzata di default in fase di link per poter creare un eseguibile a partire dal codice C contiene il codice oggetto di funzioni di base quali printf, scanf, open, read, write, etc. Il comando ar consente anche di visualizzare il contenuto di una libreria: ar t /usr/lib/libc.a pr -4 -t N.B. con la concatenazione del comando pr -4 -t (tramite la pipe) si formatta l' output di ar t /usr/lib/libc.a su 4 colonne

Formato dei le eseguibili Il formato di default con cui vengono generati gli eseguibili (Executable and Linking Format) contiene (la denizione si trova nel le intestazione <elf.h>): Un header (intestazione) contenente informazioni sul sistema per cui il codice è stato compilato (tipo di hardware, versione SO, etc.) Informazioni sui segmenti di testo e dati Informazioni relative alla rilocazione Informazioni sulla tabella dei simboli e sulla tabella delle stringhe In linux, come nel resto dei sistemi UNIX, i le eseguibili vengono identicati vericando che questi rispettino il formato ELF, e non tramite l' estensione.exe del le come avviene in Windows.

Argomenti passati dalla shell È possibile accedere agli argomenti passati ad un programma tramite riga di comando facendo uso dei parametri argc e argv della fuzione main() argc: è un valore intero che specica il numero di parametri immessi nella riga di comando (n.b.: include il nome del le eseguibile) argv: è un array di puntatori a stringhe di caratteri. Ogni elemento di argv punta a un argomento fornito nella riga di comando (comprende anche il nome del le eseguibile) Esempio. Se digitiamo cp file1.c file1.bak, la shell assegna i seguenti valori alle variabili: argc = 3 argv[0] = cp argv[1] = file1.c argv[2] = file2.bak argv[3] = NULL

Argomenti passati dalla shell Esempio Esempio. Scriviamo il seguente listato su rigacom.c: void main(int argc, char *argv[]) { int i=0; printf(``nella riga di comando sono stati inseriti %d argomenti:\n\n'', argc); for (i=0; i<argc; i++) printf(``argv[%d] = %s, '', i, argv[i]); } Compiliamo tramite gcc -o rigacom rigacom.c e eseguiamo: rigacom uno due tre quattro cinque Output: Nella riga di comando sono stati insertiti 5 argomenti: rigacom, uno, due, tre quattro, cinque

Argomenti passati dalla shell Variabili di ambiente A livello di shell in genere vengono denite delle variabili d'ambiente (visibili utilizzando il comando env o printenv). Queste possono contenere il nome dell' utente corrente, del gruppo di appartenenza, host, percorsi predeniti, etc. (maggiori informazioni tramite man environ) I processi hanno accesso alle variabili d'ambiente tramite un puntatore (es. p2.7.cxx): extern char **environ; Le variabili d' ambiente possono essere lette/modicate anche attraverso le funzioni getenv() e putenv() denite in <stdlib.h>

Gestione degli errori La chiamata ad una funzione potrebbe non andare a buon ne. Ad esempio utilizzare la funzione open() per tentare di aprire un le inesistente causerà un errore In genere le funzioni predenite del C in caso di errore restituiscono -1 e impostano il valore di una variabile globale chiamata errno La variabile globale errno è una variabile intera che contiene il codice che identica l' errore che è stato riscontrato (tutti i codici sono deniti in genere nel le header /sys/errno.h) La funzione perror() stampa a video una stringa che descrive a parole il codice di errore memorizzato in errno

Gestione degli errori Esempio #include <iostream> #include <cstdio> #include <unistd.h> using namespace std; int main(int argc, char *argv[ ]){ if (argc > 1) { execlp("/bin/cat", "cat", argv[1], (char *) NULL); perror("ho fallito l' esecuzione di cat:"); return 1; } printf("utilizzo: %s text_file\n", argv[0]); return 2; }

Gestione degli errori Esempio Se la chiamata a execlp() fallisce il risultato sarà: Ho fallito l' esecuzione di cat: dell'errore> <descrizione Nota: la funzione execlp è una delle tante funzioni front-end di execve, utile per eseguire un eseguibile di cui si conosce il nome.

Input/Output a le La gestione dell' I/O a le orientata al usso fa riferimento ad un le tramite un puntatore a tipo di dato FILE (FILE *) Le funzioni per la gestione dell'i/o di basso livello utilizzano un valore intero chiamato le handle o descrittore di le

Input/Output a le Apertura o creazione di un le Le funzioni open() e creat() presentano i seguenti prototipi: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); int creat(const char *pathname, mode_t mode); dove pathname indica il percorso del le da aprire. Il valore di flags indica la modalità di apertura del le (lettura, scrittura, etc.). Il valore di mode esprime i permessi sul le. In caso di successo le funzioni restituiscono un intero che rappresenta il primo (più piccolo) descrittore di le disponibile. In caso di errore le funzioni restituiscono -1 e impostano l'opportuno valore di errno

Input/Output a le Lettura e scrittura di un le Le funzioni read() e write() presentano i seguenti prototipi: #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); write() scrive count byte di buf nel le puntato da fd read() legge count byte dal le puntato da fd e li memorizza in buf In caso di errore restituiscono -1 e impostano l'opportuno valore di errno

Input/Output a le Esempio #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define BUFFER_LENGTH 1024 /* Esegue la copia di un file */ int main(int argc, char *argv[]) { int fd_orig, fd_dest; char buffer[buffer_length]; int num_byte = 0; continua...

Input/Output a le Esempio if ((fd_orig = open(argv[1], O_RDONLY)) == -1) { perror("open del file origine"); exit(2); } if ((fd_dest = open(argv[2], O_RDWR O_CREAT O_TRUNC, S_IRUSR S_IWUSR S_IRGRP S_IWGRP)) == -1) { perror("open del file destinazione"); exit(3); } continua...

Input/Output a le Esempio while(1) { num_byte = read(fd_orig, buffer, BUFFER_LENGTH); if (num_byte == -1 ) { perror("errore in lettura"); exit(4); } else if (num_byte==0) break; if (write(fd_dest, buffer, num_byte) == -1) { perror("errore in scrittura"); exit(5); } continua...

Input/Output a le Esempio } } return 0; /* Fine io_basso_liv.c */

Input/Output a le Verica di tipo e informazioni relative ai le La funzione isatty(): #include <unistd.h> int isatty(int desc); restituisce 1 se desc è legato ad un terminale, altrimenti restituisce 0

Input/Output a le Verica di tipo e informazioni relative ai le Le funzioni stat() e fstat(): #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *file_name, struct stat *buf); int fstat(int filedes, struct stat *buf); restituiscono informazioni sul le (timestamp dell' ultimo accesso, dell' ultima modica, UID e GID del proprietario, etc.). Le informazioni vengono salvate nella struttura dati buf (es. p2.2.cxx)

Allocazione dinamica della memoria Per questioni di ecienza e essibilità nei programmi C e C++ si utilizza spesso l'allocazione dinamica della memoria assegnata ad un certo tipo di dato L' allocazione dinamica della memoria avviene attraverso funzioni dedicate che rendono disponibile un area contigua di memoria, di dimensione (in byte) specicata, restituendone l' indirizzo della prima locazione N.B. Parliamo di memoria virtuale

Allocazione dinamica della memoria Funzioni C Le funzioni del C per l' allocazione dinamica della memoria sono: #include <stdlib.h> void *calloc(size_t nmemb, size_t size); void *malloc(size_t size); void free(void *ptr); void *realloc(void *ptr, size_t size);

Allocazione dinamica della memoria Funzioni C calloc() alloca memoria per un array di nmemb elementi di dimensione size. La memoria allocata viene inizializzata a 0 malloc() alloca size byte di memoria (non inizializza le locazioni allocate) free() libera la memoria precedentemente allocata puntata da ptr realloc() cambia la dimensione del blocco di memoria puntato da ptr calloc(), malloc() e realloc() restituiscono un puntatore al blocco di memoria allocato, oppure NULL in caso di fallimento; free() non restituisce alcun valore.

Allocazione dinamica della memoria Esempio #define SIZE_MAX 20 int func(unsigned numchar) { char *stringa = NULL; /* prevedere dei limiti all' allocazione dinamica */ if (numchar > SIZE_MAX) { numchar = SIZE_MAX; /* effettuare il cast */ stringa = (char *) malloc(sizeof(char)*numchar); if ( stringa == NULL) return -1; /* SEMPRE deallocare la memoria non piu' utile */ free(stringa); return 1; }

Allocazione dinamica della memoria Funzioni C++ Operatori new e delete: string *sp; sp = new string(``ciao''); delete sp; Allocazione di un array di oggetti: int *sp; sp = new int[10]; delete [] sp; Vedere es. mem_alloc.c e mem_alloc.cpp

Allocazione dinamica della memoria I/O da terminale in C++ Gli oggetti cin, cout e cerr cin, cout e cerr sono variabili globali dichiarate in <iostream> cin è un oggetto di tipo istream collegato allo standard input cout è un oggetto di tipo ostream collegato allo standard output cerr è un oggetto di tipo ostream collegato allo standard error

Allocazione dinamica della memoria I/O da terminale in C++ #include <iostream> using namespace std; // omettendo questa istruzione bisogna // riferirsi a cout e cin come std::cout e std::cin int main() { int i, j, k; cout << ``Inserisci tre numeri separati da uno spazio:''; cin >> i >> j >> k; if(i>100 j>100 k>100) cerr << ``Errore: i numeri devono essere < 100!'' << endl; continua...

Allocazione dinamica della memoria I/O da terminale in C++ } else cout << ``Sono stati inseriti i seguenti valori: i='' << i << ``, j='' << j << ``, k='' << k << endl; return 0;

Risorse utili John Shapley Gray, Interprocess Communications in LINUX, The Nooks & Crannies B. W. Kernighan, D. M. Ritchie, Il Linguaggio C, Prentice Hall Herbert Schildt, Guida al C++, Mc Graw Hill GNU/Linux, pagine man