41
3.2.1 3.2: Chiamate di Sistema Unix/Linux Introduzione Gestione dei canali di I/O Gestione dei file Controllo dei processi Pipe e FIFO Ambiente di lavoro dei processi Gestione dei segnali System V IPC Altre chiamate

3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

  • Upload
    dangbao

  • View
    234

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.1

3.2: Chiamate di Sistema Unix/Linux● Introduzione

● Gestione dei canali di I/O

● Gestione dei file

● Controllo dei processi

● Pipe e FIFO

● Ambiente di lavoro dei processi

● Gestione dei segnali

● System V IPC

● Altre chiamate

Page 2: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.2

Introduzione● Chiamate sistema Unix = funzioni C.

● Valore di ritorno: -1 in caso di errore, 0 se O.K. (salvo ove diversamente specificato)

● Variabile errno : #include <errno.h>

extern int errno;

● Funzioni di libreria strerror() e perror():char *strerror(int errnum);

void perror(char *errstring);

strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio esplicativo di errno.

● Si veda intro(2), perror(3).

Page 3: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.3

Introduzione (Cont.)● Inclusione tipica degli header file:

#include <sys/types.h> /* pseudo-tipi */

#include <unistd.h>

#include <stdlib.h>

● pseudo-tipi utilizzati:typedef long time_t;

typedef long off_t;

typedef unsigned int size_t;

typedef short pid_t;

...

Page 4: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.4

Gestione dei canali di I/O

● int creat(const char *path, mode_t mode);– mode = bit di protezione; modificato da umask(2)– ritorna file descriptor (f.d.) del file creato– il file è aperto in sola scrittura– es.:

fd  = creat("/tmp/tmpfile", 0600);● #include <fcntl.h>

int open(const char *path, int flags, mode_t mode);– path e mode: come per creat(2)– flags: O_RDONLY, O_WRONLY, O_RDWR;

O_APPEND, O_CREAT, O_TRUNC, O_EXCL– mode è facoltativo; è usato (obbligatoriamente) solo se c'è O_CREAT– ritorna file descriptor (f.d.) del file aperto– creat(path, mode) equivale a 

open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)– es.:

fd = open("./my_data", O_RDWR);

Page 5: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.5

Gestione dei canali di I/O (Cont.)● int close(int fd);

– fd = f.d. del file da chiudere

● int read(int fd, char *buf, size_t nb);– legge fino a nb byte dal canale identificato da fd e li scrive a partire da buf– ritorna il numero di byte effettivamente letti (<= nb), 0 se EOF, -1 se errore– es.:

nn = read(fd, buf, BUFSIZ);

● int write(int fd, const char *buf, size_t nb); – scrive nb byte sul canale identificato da fd, leggendoli a partire da buf– ritorna il numero di byte effettivamente scritti– es.:

nn = write(fd, buf, BUFSIZ);

Page 6: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.6

Gestione dei canali di I/O (Cont.)

● off_t lseek(int fd, off_t offset, int whence);– sposta l'I/O pointer (offset del prossimo read o write)– whence: SEEK_SET, SEEK_CUR, SEEK_END– offset: può essere negativo– ritorna nuovo valore dell'I/O pointer; (off_t)-1 se errore– seek oltre EOF   'buco' (zona letta come tutti 0, ma non occupa spazio

fisico)– es.:

ptr = lseek(fd, (off_t)-1024, SEEK_END);

● off_t tell(int fd);– restituisce il valore attuale dell'I/O pointer, senza modificarlo– equivale a

lseek(fd, (off_t)0, SEEK_CUR);

Page 7: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.7

Gestione dei canali di I/O (Cont.)

● int dup(int oldfd);int dup2(int oldfd, int newfd);

– associa a un f.d. aperto un nuovo f.d., clone del precedente– ritornano il nuovo f.d.– dup() sceglie il nuovo f.d. come il più piccolo disponibile– dup2() chiude prima newfd, se è già in uso– il nuovo e il vecchio f.d. condividono modo di apertura, I/O pointer, etc.– es.: ridirezione di stdout su un file

int fd;

if((fd = open("outfile", O_WRONLY|O_CREAT, 0666)) == -1)error_exit("...");

dup2(fd, 1); /* N.B. - 1 è il f.d. dello stdout */close(fd);

Page 8: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.8

Gestione dei File● int link(const char *oldpath, const char *newpath);

– hard link– crea nuovo link (nuovo alias) per un file (normale o speciale)– oldpath e newpath devono essere nello stesso file-system; oldpath deve

esistere, e non può essere una directory– esiste limite massimo al numero di hard link di un file, che è memorizzato

nell'i-node (di solito 128)– dopo l'operazione, oldpath e newpath sono indistinguibili– ritorna 0 se OK, -1 se errore

● int symlink(const char *oldpath, const char *newpath);– symbolic link– crea link simbolico (nuovo alias) per un file (normale o speciale o directory)– oldpath e newpath possono non appartenere allo stesso file-system; oldpath

può non esistere, e può anche essere una directory– ritorna 0 se OK, -1 se errore

Page 9: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.9

Gestione dei File (Cont.)

● int unlink(const char *path);– rimuove un hard link per il file:

● decrementa link count nello i-node● libera la entry della directory

– se il link era l'ultimo (link count scende da 1 a 0), il file è rimosso (blocchi di dati e i-node deallocati)

– es.: rinomina di un filelink("pippo", "pluto");unlink("pippo");

● int truncate(const char *path, off_t length);int ftruncate(int fd, off_t length);

– il file identificato da path o da fd è troncato; la sua dimensione è al massimo di length byte (eventuali dati oltre length vengono persi)

– con ftruncate(), il file deve essere aperto in scrittura

Page 10: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.10

Gestione dei File (Cont.)

● int access(const char *path, int mode);– verifica la possibilità di accesso ad un file, da parte del processo– mode: R_OK, W_OK, X_OK, F_OK (o una combinazione di questi, con 

bitwise­OR)– es.:

if(access("file", R_OK|W_OK) == ­1)printf("cannot open file in RDWR mode\n");

● #include <sys/stat.h>int chmod(const char *path, mode_t mode);int fchmod(int fd, mode_t mode);– cambia i bit di protezione di un file, dato un path o un fd– es.:

fchmod(fd, 0600);● int chown(const char *path, uid_t uid, gid_t gid);

int fchown(int fd, uid_t uid, gid_t gid);– cambia proprietario e gruppo di un file– uid e gid vanno specificati come valori numerici

Page 11: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.11

Gestione dei File (Cont.)● #include <sys/stat.h>

int stat(const char *path, struct stat *buf);int lstat(const char *path, struct stat *buf);fstat(int fd, struct stat *buf);– restituisce stato dell'i­node di un file, dato un path o un fd– lstat() si riferisce al file link simbolico (se è il caso), non a quello puntato– retval == ­1  errno == ENOENT ­  il file non esiste– struct stat {

        dev_t         st_dev;       /* device */        ino_t          st_ino /* inode number */        umode_t    st_mode; /* file type + set­UID etc. + protection */        nlink_t        st_nlink;     /* number of hard links */        uid_t          st_uid;       /* user ID of owner */        gid_t          st_gid;       /* group ID of owner */        dev_t         st_rdev;      /* device type (if special file) */        off_t           st_size;      /* total size, in bytes */        ...        time_t        st_atime;     /* time of last access */        time_t        st_mtime;     /* time of last modification */        time_t        st_ctime;     /* time of last change */};

Page 12: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.12

Gestione dei File (Cont.)● sys/stat.h definisce vari simboli e macro applicabili al membro st_mode

(v. stat(2)):

– S_ISREG(m), S_ISDIR(m), S_ISCHR(m), etc.

● Vero se il file è un file regolare, una directory, uno special file di tipo carattere, etc.

– S_IFMT

● Bit mask per isolare il tipo di file

– S_ISUID, S_ISGID, ISVTX, etc.

● Bit set-UID, set-GID, sticky bit, etc.

Page 13: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.13

Controllo dei Processi● pid_t fork(void);

– crea nuovo processo (child ­ figlio), duplicando quello originale (parent ­ padre)

– ritorna● al figlio: (pid_t)0● al padre: il PID del figlio appena creato● in caso di errore, (pid_t)­1 (al padre)

– il processo figlio eredita tutto l'ambiente del padre, compresi i canali aperti (tutto tranne il PID)

– il figlio si trova come se avesse eseguito tutto il programma fino al fork, come il padre

– es.:if(pid = fork()){ /* padre */

if(pid == (pid_t)­1) { perror("fork"); exit(1); }...

} else {/* figlio */...

}● Linux supporta i kernel threads con la chiamata clone(2)

Page 14: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.14

Controllo dei Processi (Cont.)● int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);int execv(const char *path, char *const argv[]);int execvp(const char *file, char * const argv[]);– sostituisce, nel processo corrente, un nuovo programma all'attuale, e lo 

esegue– il processo rimane lo stesso, quindi tutto l'ambiente è inalterato– execlp() ed execvp() usano la variabile di environment PATH per cercare il 

file– execl(), execlp(): arg e gli argomenti successivi sono arg0, arg1, etc.; l'ultimo 

argomento deve essere un NULL pointer– execv(), execvp(): argv è un array già nel formato atteso dalla function 

main()– sono in realtà tutti front­end di un'unica system call, execve(2)– 'viaggio senza ritorno': se c'è un valore di ritorno, è ­1 (impossibile eseguire 

il nuovo programma)– es.: 

execl("/bin/cat", "cat", "/tmp/tmpfile", NULL);  printf("cannot execute program!\n");

Page 15: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.15

Controllo dei Processi (Cont.)● void exit(int code);

– termina il processo– flush dell'I/O pending (stdout etc.), chiude tutti i file, esce– non ritorna mai

● #include <sys/wait.h>pid_t wait(int *status_addr);– aspetta finchè uno dei processi figli termina– ritorna il PID del primo figlio che ha terminato– se status_addr non è NULL, ritorna anche, nell'intero puntato, lo stato 

d'uscita del figlio:● exit code● segnale che ha eventualmente terminato il processo, e altre 

informazioni– lo stato d'uscita può essere analizzato con le macro WEXITSTATUS(), 

WIFEXITED(), WIFSIGNALED(), WTERMSIG(), WCOREDUMP() e altre ­ vedere wait(2)

– variante: waitpid(2)– es.:

while(wait(NULL) != (pid_t)­1); /* wait for all children */

Page 16: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.16

Controllo dei Processi (Cont.)● Combinazione tipica delle chiamate viste:

pid_t pid;int exstatus, excode;

if(pid = fork()){

/* processo padre */if(pid == (pid_t)­1)

error_exit("cannot fork\n");...while(wait(&exstatus) != pid && pid != (pid_t)­1)

;excode = WEXITSTATUS(exstatus);exit(excode); /* esce col codice del figlio */

}else{

/* processo figlio *//* ...  eventuale ridirezione dell'I/O */execl("/usr/local/bin/program", "program", "­x", "file", NULL);error_exit("cannot exec program\n");

}

Page 17: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.17

Pipe e FIFO

● Costituiscono il meccanismo più semplice di comunicazione interprocesso

● int pipe(int fdc[2]);– stabilisce un canale di comunicazione tra processi, che può essere

condiviso con i processi figli– il canale è unidirezionale– fdc[0] serve per leggere dal pipe, fdc[1] per scrivere– il pipe è implementato come un file anonimo, di lunghezza massima fissa (di

solito pari a 4 Kbyte), con seek impliciti per comportamento da FIFO– sincronizzazione automatica di processi scrittori e lettori in caso di pipe

pieno/vuoto– EOF (0 byte letti) ritornato dalla read() al lettore se non c’è più nessuno

scrittore– SIGPIPE inviato allo scrittore per una write() se non c’è più nessun lettore– è fondamentale orientare il pipe prima di utilizzarlo

Page 18: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.18

Pipe e FIFO (Cont.)

● FIFO = pipe con nome (named pipe), che esiste in modo permanente.

● mknod(2) = creazione di special file, FIFO e altro. Relativamente complicata da utilizzare.

● mkfifo(3) = funzione di libreria (specifica POSIX).● #include <sys/stat.h>

int mkfifo(const char *path, mode_t mode);– crea un FIFO

– comportamento identico a quello di un pipe, salvo che il file non è anonimo

– un processo che apre il FIFO in scrittura resta bloccato sulla open(2) finchè un altro lo apre in lettura, e viceversa

– se mode contiene altri bit oltre quelli di protezione, il loro significato è “implementation-defined” (POSIX).

Page 19: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.19

Ambiente di lavoro dei processi● int chdir(const char *path);

● int chroot(const char *path);

– cambia la directory di lavoro (chdir) o la directory radice (chroot) del processo

● pid_t getpid(void);

● pid_t getppid(void);

– restituisce il proprio PID (getpid), o quello del proprio processo padre (getppid)

● uid_t getuid(void);

● uid_t geteuid(void);

● gid_t getgid(void);

● gid_t getegid(void);

– restituisce lo user-ID reale (getuid) o effettivo (geteuid), ovvero il group-ID reale (getgid) o effettivo (getegid) del processo

Page 20: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.20

Ambiente di lavoro dei processi (Cont.)● int setuid(uid_t uid);

● int setgid(gid_t gid);

– stabilisce un nuovo user­ID (setuid) o un nuovo group­ID (setgid) per il processo

– normalmente riservate al super­user

– N.B. ­ fare prima setgid(), poi setuid()

●  int umask(int mask);

– nuova maschera di creazione dei file

– mask: in open(2), creat(2), mkfifo(3) il vero modo è dato da mode & ~umask● int nice(int incr);

– incrementa priorità numerica del processo

– priorità: 0 (alta) ÷ 40 (bassa); default: 20

– root puo` specificare incr negativo (alzare la priorità)● N.B. ­ v. anche getenv(3), putenv(3), in “Altre chiamate”

Page 21: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.21

Gestione dei segnali● Segnale: provoca interrupt software nel processo ricevente

● Azione di default all’interrupt: a) exit b) core-dump + exit [*]

● Segnali principali (vedi signal(2)):

– SIGHUP (1) ­ terminale chiuso o scollegato

– SIGINT (2)   ­ intr char. da terminale

– SIGQUIT (3) ­ quit char. da terminale [*]

– SIGILL (4) ­ istruzione illegale

– SIGKILL (9) ­ terminazione forzata (non intercettabile)

– SIGSEGV (11) ­ violazione spazio memoria [*]

– SIGPIPE (13) ­ scrittura in pipe senza processo lettore

– SIGALRM (14) ­ orologio allarme scaduto

– SIGTERM (15) ­ terminazione software (default per kill(1))

– SIGCHLD (17) ­ morte di un processo figlio

– ­SIGUSR1, SIGUSR2 (10, 12) – user­defined

● Linux supporta anche segnali detti real-time (sono accodati).

Page 22: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.22

Gestione dei segnali (Cont.)● #include <signal.h>

int kill(pid_t pid, int sig);

– invia il segnale sig al processo con PID pari a pid

– processo ricevente: deve avere stesso UID del processo mittente (salvo se mittente è root)

– se pid == -1: invia segnale a tutti i processi (eccetto a init(8), PID == 1)

– se pid < -1: invia segnale al process-group -pid (PID del process-group leader, ovvero primo processo che ha aperto il terminale di controllo)

– es.:

/* processo suicida; lascia core dump ai posteri */

kill(SIGQUIT, getpid());

Page 23: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.23

Gestione dei segnali (Cont.)● #include <signal.h>

void (*signal(int sig, void (*handler)(int)))(int);– alla ricezione di sig, viene eseguita la routine di interrupt puntata da handler

– handler == SIG_DFL: viene (re)installata azione di default

– handler == SIG_IGN: il segnale viene ignorato

– retval = valore precedente di handler per quel segnale

– (*handler)() è chiamato con un argomento: segnale che ha generato l’interrupt

– ad ogni interrupt, l’azione installata è resettata a SIG_DFL; (*handler)() deve eventualmente richiamare signal(2) per reinstallare la routine

– segnale arriva durante una sys.call lenta (read(2) da tty, wait(2), pause(2) etc. ­ processo in attesa di evento): ritorno prematuro, retval == ­1, errno == EINTR

– processo che non aspetta (wait(2)) i suoi figli (es. tipico: server concorrente): per evitare di lasciarli in ZOMBIE state, deve ignorare SIGCHLD:

signal(SIGCHLD, SIG_IGN);/* avoid zombie children */

Page 24: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.24

Gestione dei segnali (Cont.)● Uso tipico della chiamata signal(2):

#include <signal.h>

void trap_intr(int); /* signal interrupt routine */

void (*fp)(int); /* a function pointer */

fp = signal(SIGTERM, trap_intr);

/* critical code */

/* end of critical code */

signal(SIGTERM, fp); /* reinstall previous action */

void trap_intr(int sig)

{

signal(sig, trap_intr); /* handle receipt of all subsequent interrupts */

}

● Variante: sigaction(2), sigprocmask(2), sigpending(2), sigsuspend(2)

Page 25: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.25

Gestione dei segnali (Cont.)● int pause(void);

– sospende processo, per sempre (o fino a ricezione di segnale)

– il processo va a dormire; non consuma CPU

● unsigned alarm(unsigned sec);

– invia il segnale SIGALRM al processo corrente dopo sec secondi

– risoluzione: 1 secondo

– alarm(0) resetta il meccanismo

– retval: numero di secondi mancanti al termine dell’eventuale alarm precedente

– es.: read from serial line or socket, with timeout

signal(SIGALRM, timeout);

alarm(10); /* 10 seconds max. time */

nn = read(fd, buf, BUFSIZ);

alarm(0); /* reset timeout */

if(nn == -1) {

if(errno == EINTR) printf(“read timeout expired\n”);else error_exit(“read error\n”);

}

Page 26: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.26

Gestione dei segnali (Cont.)● unsigned sleep(unsigned sec);

– funzione di libreria

– sospende processo per sec secondi

– retval: 0 se tempo scaduto, n. di secondi restanti se ritorno prematuro

– implementata con signal(2) + alarm(2) + pause(2)

Page 27: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.27

IPC di System V● Gli IPC risolvono alcune limitazioni degli altri meccanismi di

comunicazione tra processi:

– i pipe sono limitati a processi con relazione di parentela

– i FIFO non risolvono bene lo scambio dati tra più di 2 processi

● Ogni oggetto IPC è un oggetto permanente:

– vive anche dopo la terminazione del processo che lo ha creato

– occupa spazio nell’indirizzamento virtuale del kernel

– è swappabile

● Ogni oggetto IPC ha un nome unico: chiave (key), intero positivo.

● La chiave si alloca con la funzione di libreria ftok(3):# include <sys/types.h># include <sys/ipc.h>key_t ftok ( char *pathname, char proj )

– genera chiave unica in funzione del pathname di un file e di un identificativo di progetto, proj.

Page 28: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.28

IPC di System V (Cont.)

● Analogia file - IPC:– nome (char string) ↔ chiave (long int)– file descriptor (int) ↔ identificatore (int)– inode (data struct.) ↔ descriptor (data struct):

msqid_ds, shmid_ds, semid_ds

● Operazioni di base su oggetti IPC:– get() ↔ open(), creat() -- id = get(key);– ctl() ↔ ioctl(), unlink() -- ctl(id);– op() ↔ read(), write(), etc. -- op(id);

read, write mesg.

attach, detach shm.

modify sem.

Page 29: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.29

IPC di System V (Cont.)

● Flags per get() e ctl():– IPC_CREAT, IPC_EXCL; IPC_NOWAIT

● comandi per ctl():– IPC_RMID (distruz.), IPC_SET (modifica caratteristiche), IPC_STAT

(leggi statistiche)● Gli oggetti IPC esistenti possono essere controllati con ipcs(8) e

rimossi con ipcrm(8).

Page 30: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.30

Code di Messaggi

● Mantengono memorizzati messaggi in modo permanente, finchè un processo li estrae dalla coda.

● # include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int flag);

– crea coda di messaggi, data una chiave key

– restituisce l’identificatore (id)

– flag: bit di protezione (es. 0660), OR-ed con IPC_CREAT, IPC_EXCL (errore se l’oggetto esiste già)

● int msgctl(int id, int cmd, struct msqid_ds *buf);

– id: identificatore (restituito da msgget())

– cmd: IPC_RMID -> distruggi la coda; buf è ignorato

– retval: 0 (OK) o -1 (errore).

Page 31: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.31

Code di Messaggi (Cont.)

● int msgsnd(int id, const void *msg, size_t size, int flag);

– invia un messaggio in una coda

– id: identificatore della coda

– msg: punta a una struttura del tipostruct msgbuf {

long mtype; /* tipo messaggio (>= 0) */char mtext[MSIZE]; /* messaggio, max. MSIZE car. */

};– size: numero byte in mtext[ ] da trasferire

– flag: 0 o IPC_NOWAIT → se la coda è piena, non sospendere processo ma ritorna in errore

– nel messaggio viene memorizzato sia msg->mtype (4 byte) che msg->mtext[ ] (size byte)

– retval: 0 (OK) or -1 (error).

Page 32: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.32

Code di Messaggi (Cont.)

● int msgrcv(int id, void *msg, size_t size, long type, int flag);

– estrae un messaggio da una coda

– id: identificatore della coda

– msg: punta a una struttura di tipo msgbuf (v. slide precedente)

– size: numero max. di byte da trasferire in msg->mtext[ ] (oltre ai 4 byte di msg->mtype, trasferiti comunque)

– type: tipo messaggio (in msg->mtype)● type > 0 estrai un messaggio di tipo type● type = 0 estrai qualunque messaggio● type < 0 estrai messaggio di tipo <= -type, scegliendo

in ordine crescente di tipo (dal più basso)– i messaggi vengono estratti in ordine di inserzione (dapprima i più vecchi)

– flag: 0 o IPC_NOWAIT → se la coda è vuota (rispetto al tipo di messaggio voluto), non sospendere processo ma ritorna in errore

– retval: numero di byte copiati in msg->mtext[ ], o -1 (errore).

Page 33: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.33

Memoria Condivisa

● Una zona di memoria condivisa (shared memory) va creata, quindi collegata al proprio spazio di indirizzamento da parte di uno o più processi, e infine usata; per usarla non occorre nessuna chiamata particolare, basta accedere alla memoria stessa.

● # include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, int size, int flag);

– crea memoria condivisa, grande size byte, data una chiave key

– restituisce l’identificatore (id)

– flag: come per msgget()

● int shmctl(int id, int cmd, struct shmid_ds *buf);

– id: identificatore (restituito da shmget())

– cmd: IPC_RMID -> distruggi la memoria; buf è ignorato

– retval: 0 (OK) o -1 (errore).

Page 34: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.34

Memoria Condivisa (Cont.)

● void *shmat(int id, void *addr, int flag);

– collega una memoria condivisa al proprio spazio di indirizzamento

– id: identificatore

– addr: indirizzo a cui si vuole collegare; se è NULL, sceglie il sistema

– flag: specifica modalità di accesso● SHM_R, SHM_W, SHM_RW - read, write, read-write

– retval: indirizzo effettivo di collegamento, o (void *)-1 (errore)

● int shmdt(const void *addr);

– scollega una memoria condivisa

– addr: indirizzo della memoria da scollegare

– retval: 0 (OK) o -1 (errore).

Page 35: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.35

Semafori

● Ciascun oggetto IPC semaforo implementa un array di semafori, i cui elementi possono essere modificati (operazioni signal e wait) tutti insieme in modo atomico.

● # include <sys/ipc.h>#include <sys/sem.h>int semget(key_t key, int nsems, int flag);

– crea semaforo, con nsems elementi, data una chiave key

– restituisce l’identificatore (id)

– flag: come per msgget()

Page 36: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.36

Semafori (Cont.)● int semctl(int id, int semnum, int cmd, union semun arg);

– serve per

● rimuovere semaforo● assegnare valore iniziale, leggere valore attuale

– id: identificatore (restituito da semget())

– arg: la union è fatta così:

union semun {

int val;ushort *array;

};– cmd:

● IPC_RMID: distruggi il semaforo; gli altri parametri sono ignorati● GETVAL: retval = valore dell’elem. n. semnum del semaforo● SETVAL: assegna arg.val all’elem. n. semnum del semaforo● GETALL: leggi valori di tutti gli elementi e copiali in arg.array● SETALL: copia i valori di tutti gli elementi da arg.array

– retval: (salvo il caso GETVAL): 0 (OK) o -1 (errore).

Page 37: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.37

Semafori (Cont.)

● int semop(int id, struct sembuf *sops, unsigned nsops);

– implementa operazioni di increm./decrem. (signal / wait) su nsops elementi di un semaforo

– id: identificatore (restituito da semget())

– sops: punta ad array di nsops struct così fatte:

struct sembuf {ushort sem_num; /* elem. su cui operare */short sem_op; /* operazione */short sem_flag; /* opzioni (0 o IPC_NOWAIT) */

};– sem_op è un valore da sommare algebricamente al valore dell’elemento del

semaforo (sem_val):

Page 38: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.38

Semafori (Cont.)

● a) sem_op < 0 : allocazione risorsa (wait)

if(semval >= abs(sem_op)) { semval -= abs(sem_op); return OK; } else { if(sem_flg & IPC_NOWAIT) return -1; else { wait till semval >= abs(sem_op); semval -= abs(sem_op); return OK; } }

● b) sem_op > 0 : liberazione risorsa (signal)

semval += sem_op; return OK;

● c) sem_op == 0 : attesa di semaforo nullo

if(semval == 0) return OK; else { if(sem_flg & IPC_NOWAIT) return -1; else { wait till semval == 0; return OK; } }

Page 39: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.39

Altre chiamate● #include <sys/times.h>

clock_t times(struct tms *buf);

– struttura tms : definita come segue

struct tms

{

time_t tms_utime; /* user time */

time_t tms_stime; /* system time */

time_t tms_cutime; /* user time of children */

time_t tms_cstime; /* system time of children */

};– ritorna in *buf tempo CPU in user- e system (kernel)-mode, per processo e

per i figli terminati (cumulato)

– tempi espressi in clock ticks del sistema (di solito 10 msec.)

● Il valore può essere ottenuto tramite sysconf(3):

ticks_per_second = sysconf(_SC_CLK_TCK);– retval: tempo dal bootstrap (istante arbitrario - usare solo per differenze)

Page 40: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.40

Altre chiamate (Cont.)

● time_t time(time_t *timep);

– retval: data e ora attuale (n. di secondi dal 1/1/1970, 00:00, GMT)

– se timep non è NULL, ritorna stesso valore anche lì

– N.B. - l’ora interna e` sempre quella di Greenwich; il valore ritornato da time(2) va poi scalato secondo time-zone (vedi ad es. localtime(3))

– variante: gettimeofday(2)● #include <sys/wait.h>

int system(const char *cmd);

– funzione di libreria, implementata con fork(2) + exec(2) + wait(2) + sh(1)

– cmd: shell command line (con metacaratteri, etc.)

– retval: process exit status, ritornato da wait(2) (e non lo exit code)

– es.:

xs = system(“cc -o prog *.c >cc.LOG 2>&1”);exit(WEXITSTATUS(xs));

Page 41: 3.2: Chiamate di Sistema Unix/Linux - Vito Asta - Home Page · strerror() restituisce messaggio esplicativo del valore di errnum; perror() stampa a stderr errstring seguita da messaggio

3.2.41

Altre chiamate (Cont.)

● char *getenv(const char *var);

int putenv(const char *string);

– funzioni di libreria per gestione environment

– environment: array di puntatori a stringhe, identico ad argv di main()

extern char **environ;– ogni stringa è del tipo “var=string”

– getenv(3): retval = valore della variabile di envir. var, o NULL se non è definita

– putenv(3) inserisce una variabile di environment (sostituendo eventuale valore precedente); retval = 0 se OK, -1 se errore

– es.:

char *home = getenv(“HOME”);

putenv(“USERNAME=luca”);