Esercizi con System Call
Questi programmi contengono esempi di uso delle System-Call.
Il consiglio e' di compilarli, provarli e capirne passo-passo il funzionamento. (o spiegare perche' non funzionino).
Ovviamente potete proporre ulteriori esempi. Renzo (talk) 08:03, 2 November 2015 (CET)
programma 0
Il gatto di Schrödinger: Fork e' vero o falso?
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
if (fork())
printf("fork is true\n");
else
printf("fork is false\n");
usleep(100000);
return 0;
}
il programma stampa entrambi i risultati perché la system call fork() crea un processo figlio identico al padre, questa system call ha come valore di ritorno al thread padre il pid del processo figlio (che essendo diverso da 0 è true) e al thread figlio ritorna 0, quindi il processo padre riceve un valore diverso da 0 (pid del figlio) e stampa true, mentre il processo figlio riceve 0, non entra nel if e stampa, ovviamente false.
(Simone)
programma 1
Open() Write() Read()
/*IL PROGRAMMA APRE UN FILE SUL QUALE FA DELLE OPERAZIONI DI LETTURA E SCRITTURA*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_CHAR 100000
int main(int argc, char *argv[]){
int fd, c, n_read;
int fine = EOF;
int index = 0;
char arr[MAX_CHAR];
char c_arr_read[MAX_CHAR];
const char *path = //inserisci qui il percorso del file che vuoi aprire, se il file specificato non esiste, la open fallisce e il
//programma termina con un codice di errore
fd = open(path, O_RDWR);
if(fd == -1){
printf("fd: %d\n", fd);
printf("Open failed, Err: %d\n", errno);
exit(1);
}
if( (n_read = read(fd, &c_arr_read, MAX_CHAR)) > 0 ) {
printf("file non vuoto\nbytes letti: %d\n", n_read);
write(fd, &fine, 0);
} else printf("file vuoto\nbytes letti: %d\n", n_read);
//printf("fd: %d\n", fd);
printf("Open().\n");
while((c = getchar()) != EOF && index < MAX_CHAR){
arr[index] = c;
index++;
}
//printf("sizeof arr: %d\n", sizeof(arr));
write(fd, &arr, index);
return 0;
}
(Alessio)
programma 2
segnali + fork
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <pty.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFSIZE 1024
sigset_t usr12mask;
sigset_t usr1mask;
int status;
int fd, fdout;
char name[80];
static int bit;
char *ar[2] = {"bash", NULL};
void usr12action(int num, siginfo_t *info, void *useless) {
if (num == SIGCHLD)
bit=-1;
else {
bit = (num == SIGUSR2);
kill(info->si_pid, SIGUSR1);
}
}
void usr1action(int num, siginfo_t *info, void *useless) {
}
void char_to_bin(unsigned char x, void *rec){
int i;
pid_t *r = rec;
for(i=7; i>=0; i--){
char f = x >> i & 1;
kill(*r,f?SIGUSR2:SIGUSR1);
sigsuspend(&usr1mask);
}
}
int readbit(void *v)
{
sigsuspend(&usr12mask);
return bit;
}
int bin2char(int (*f)(void *opaque), void *opaque) {
int i;
int c;
for (i=c=0; i<8; i++) {
int n=f(opaque);
if (n<0)
return -1;
c = c<<1 | n;
}
}
void main(int argc, char *argv[]){
if (argc == 1) {
pid_t pid = fork ();
if(pid > 0){
int c;
static struct sigaction sa={
.sa_sigaction=usr12action,
.sa_flags=SA_SIGINFO
};
printf("%d\n",getpid());
sigfillset(&usr12mask);
sigdelset(&usr12mask,SIGINT);
sigprocmask(SIG_SETMASK,&usr12mask,NULL);
sigdelset(&usr12mask,SIGCHLD);
sigdelset(&usr12mask,SIGUSR1);
sigdelset(&usr12mask,SIGUSR2);
sigaction(SIGUSR1,&sa,NULL);
sigaction(SIGUSR2,&sa,NULL);
sigaction(SIGCHLD,&sa,NULL);
while ((c=bin2char(readbit,stdin)) != EOF)
putchar(c);
if (waitpid(pid, &status, 0) != pid) status = -1;
}
else {
char *path;
char *sppid;
pid_t ppid=getppid();
asprintf(&path,"/proc/%d/exe",ppid);
asprintf(&sppid,"%d",ppid);
execl("/usr/bin/xterm", "xterm", "-e", path, sppid, (void *) 0);
exit(1);
}
} else {
unsigned char buf[BUFSIZE];
unsigned char *s;
pid_t receiver=atoi(argv[1]);
static struct sigaction sa={.sa_sigaction=usr1action};
sigaction(SIGUSR1,&sa,NULL);
printf("%d->%d\n",getpid(),receiver);
sigfillset(&usr1mask);
sigdelset(&usr1mask,SIGINT);
sigprocmask(SIG_SETMASK,&usr1mask,NULL);
sigdelset(&usr1mask,SIGUSR1);
if (argc == 2){
while ((s=fgets(buf,BUFSIZE,stdin))!=NULL){
while (*s){
char_to_bin(*s++, &receiver);
}
}
}
printf("\n");
}
}
il programma in questione "unisce" di fatto i due programmi sigsend e sigrec. l'idea è quella che venga lanciato un unico processo e aprire un nuovo terminale dove contiunare l'esecuzione del figlio creato attraverso la fork. Possiamo quindi sfruttare il fatto che i due processi (essendo padre e figlio) conoscono i rispettivi pid e quindi automatizzare questa parte senza fornire alcun pid in input. è possibile anche fornire un pid come argomento per comunicare con processi diversi.