├── .gitignore ├── data_files ├── matrix.txt └── quote.txt ├── syscalls_sig ├── makefile ├── sigtimer.c ├── signals.c ├── sighup.c └── syscallssig.howto ├── syscalls_ipc ├── makefile ├── syscallsipc.howto ├── server.c ├── pipe.c ├── client.c ├── socket.c └── mmap.c ├── syscalls_proc ├── forkfor.c ├── makefile ├── forkseq.c ├── forkexecl.c ├── forkaddr.c ├── syscallsproc.howto ├── shexecl.c └── shexecvp.c ├── syscalls_files ├── makefile ├── syscallsfiles.howto ├── fdir.c ├── fbasic.c └── fstat.c ├── libc_files ├── makefile ├── libcfiles.howto ├── fblock.c ├── getline.c ├── fchar.c └── getopt.c ├── lib_complex ├── makefile ├── complex.h ├── use_complex.c ├── libcomplex_howto.txt └── complex.c ├── libc_strings ├── strsep.c ├── strstr.c ├── libcfiles.howto ├── makefile ├── strargs.c └── strbasic.c └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /data_files/matrix.txt: -------------------------------------------------------------------------------- 1 | 4 2 | 5 4 4 7 3 | 1 7 8 5 4 | 4 2 4 4 5 | 8 7 5 1 6 | -------------------------------------------------------------------------------- /syscalls_sig/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: 4 | gcc -Wall signals.c -o signals 5 | gcc -Wall sighup.c -o sighup 6 | gcc -Wall sigtimer.c -o sigtimer 7 | 8 | clean: 9 | rm -f *~ signals sighup sigtimer 10 | 11 | -------------------------------------------------------------------------------- /syscalls_ipc/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: 4 | gcc -Wall mmap.c -o mmap 5 | gcc -Wall pipe.c -o pipe 6 | gcc -Wall socket.c -o socket 7 | gcc -Wall server.c -o server 8 | gcc -Wall client.c -o client 9 | 10 | clean: 11 | rm -f *~ mmap pipe socket server client 12 | 13 | -------------------------------------------------------------------------------- /data_files/quote.txt: -------------------------------------------------------------------------------- 1 | Such is the nature of evil. 2 | Out there in the vast ignorance of the world it festers and spreads. 3 | A shadow that grows in the dark. 4 | A sleepless malice as black as the oncoming wall of night. 5 | So it ever was. 6 | So will it always be. 7 | In time all foul things come forth. 8 | 9 | -- Thranduil, Elven King 10 | -------------------------------------------------------------------------------- /syscalls_proc/forkfor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) { 6 | pid_t pid; 7 | 8 | /* fork child processes */ 9 | for ( int i = 0 ; i < 3 ; i++ ) 10 | if((pid = fork()) > 0) 11 | printf("parent: %d new child: %d\n", getpid(), pid); 12 | 13 | exit(EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /syscalls_proc/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: 4 | gcc -Wall forkseq.c -o forkseq 5 | gcc -Wall forkfor.c -o forkfor 6 | gcc -Wall forkaddr.c -o forkaddr 7 | gcc -Wall forkexecl.c -o forkexecl 8 | gcc -Wall shexecl.c -o shexecl 9 | gcc -Wall shexecvp.c -o shexecvp 10 | 11 | clean: 12 | rm -f *~ forkseq forkfor forkaddr forkexecl shexecl shexecvp 13 | 14 | -------------------------------------------------------------------------------- /syscalls_files/makefile: -------------------------------------------------------------------------------- 1 | DATA=../data_files/lusiadas.txt 2 | 3 | .PHONY: all fbasic fstat fdir clean 4 | 5 | all: fbasic fstat fdir 6 | 7 | fbasic: 8 | gcc -Wall fbasic.c -o fbasic 9 | ./fbasic ${DATA} 10 | 11 | fstat: 12 | gcc -Wall fstat.c -o fstat 13 | ./fstat ${DATA} 14 | 15 | fdir: 16 | gcc -Wall fdir.c -o fdir 17 | ./fdir . 18 | 19 | clean: 20 | rm -f *~ fbasic fstat fdir 21 | 22 | -------------------------------------------------------------------------------- /syscalls_files/syscallsfiles.howto: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To make and run fbasic (example: open, read, write, close) 4 | 5 | $ make fbasic 6 | 7 | To make and run stat (example: stat) 8 | 9 | $ make stat 10 | 11 | To make and run fdir (example: opendir, readdir, closedir) 12 | 13 | $ make fdir 14 | 15 | *********************************************************** -------------------------------------------------------------------------------- /libc_files/makefile: -------------------------------------------------------------------------------- 1 | DATA=../data_files/lusiadas.txt 2 | 3 | .PHONY: all fchar fblock getline clean 4 | 5 | all: fchar fblock getline 6 | 7 | fchar: 8 | gcc -Wall fchar.c -o fchar 9 | ./fchar ${DATA} 10 | 11 | fblock: 12 | gcc -Wall fblock.c -o fblock 13 | ./fblock ${DATA} 14 | 15 | getline: 16 | gcc -Wall getline.c -o getline 17 | ./getline ${DATA} 18 | 19 | clean: 20 | rm -f *~ fchar fblock getline 21 | 22 | -------------------------------------------------------------------------------- /lib_complex/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: libs libd use clean 2 | 3 | libs: 4 | gcc -Wall -c complex.c 5 | ar -rc libcomplex.a complex.o 6 | nm -g libcomplex.a 7 | 8 | libd: 9 | gcc -Wall -fPIC -c complex.c -o complex.o 10 | gcc -shared complex.o -o libcomplex.so 11 | nm -g libcomplex.so 12 | 13 | use: 14 | gcc -Wall use_complex.c -o use_complex -L. -lcomplex -lm 15 | 16 | clean: 17 | rm -f *.o *.a *.so *~ use_complex 18 | -------------------------------------------------------------------------------- /libc_files/libcfiles.howto: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To build all executables: 4 | 5 | $ make 6 | 7 | or 8 | 9 | $ make all 10 | 11 | To build and run fchar: 12 | 13 | $ make fchar 14 | 15 | To build and run fblock: 16 | 17 | $ make fblock 18 | 19 | To build and run getline: 20 | 21 | $ make getline 22 | 23 | To remove temporary files and executable 24 | 25 | $ make clean 26 | 27 | *********************************************************** -------------------------------------------------------------------------------- /libc_strings/strsep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * simple string manipulation: strdup, strsep 7 | */ 8 | 9 | int main(int argc, char* argv[]) { 10 | int count = 0; 11 | char* text = strdup(argv[1]); 12 | char* word; 13 | while ((word = strsep(&text, " \t")) != NULL) { 14 | if ( *word == '\0' ) /* skip multiple occurrences of delimiter */ 15 | continue; 16 | printf("%s\n", word); 17 | count++; 18 | } 19 | printf("%d words found\n", count); 20 | exit(EXIT_SUCCESS); 21 | } 22 | -------------------------------------------------------------------------------- /libc_strings/strstr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * simple string manipulation: strdup, strstr 7 | */ 8 | 9 | int main(int argc, char *argv[]) { 10 | char* needle = strdup(argv[1]); 11 | char* haystack = strdup(argv[2]); 12 | 13 | char* ptr = haystack; 14 | while( (ptr = strstr(ptr, needle)) != NULL ) { 15 | int pos = strlen(haystack) - strlen(ptr); 16 | printf("[%s @ %d]\n", needle, pos); 17 | ptr++; 18 | } 19 | free(needle); 20 | free(haystack); 21 | exit(EXIT_SUCCESS); 22 | } 23 | -------------------------------------------------------------------------------- /libc_strings/libcfiles.howto: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To build and run strargs (example: argv, strcmp) 4 | 5 | $ make strargs 6 | 7 | To build and run strbasic (example: strdup, strcmp, strcpy) 8 | 9 | $ make strbasic 10 | 11 | To build and run strstr (example: strdup, strstr) 12 | 13 | $ make strstr 14 | 15 | To build and run strsep (example: strdup, strsep) 16 | 17 | $ make strsep 18 | 19 | To remove temporary files and executable 20 | 21 | $ make clean 22 | 23 | *********************************************************** -------------------------------------------------------------------------------- /syscalls_proc/forkseq.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) { 6 | pid_t pid; 7 | 8 | /* fork a child process */ 9 | if((pid = fork()) > 0) 10 | printf("parent: %d new child: %d\n", getpid(), pid); 11 | 12 | /* fork another child process */ 13 | if((pid = fork()) > 0) 14 | printf("parent: %d new child: %d\n", getpid(), pid); 15 | 16 | /* and fork another */ 17 | if((pid = fork()) > 0) 18 | printf("parent: %d new child: %d\n", getpid(), pid); 19 | 20 | exit(EXIT_SUCCESS); 21 | } 22 | -------------------------------------------------------------------------------- /libc_strings/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all strargs strbasic strstr strsep clean 2 | 3 | all: strargs strbasic strstr strsep 4 | 5 | strargs: 6 | gcc -Wall strargs.c -o strargs 7 | ./strargs -u -l -f f1.txt 8 | ./strargs -u -f f1.txt 9 | ./strargs -l 10 | 11 | strbasic: 12 | gcc -Wall strbasic.c -o strbasic 13 | ./strbasic "to be or not to be" "to be both" 14 | 15 | strstr: 16 | gcc -Wall strstr.c -o strstr 17 | ./strstr "be" "to be or not to be or to be both" 18 | 19 | strsep: 20 | gcc -Wall strsep.c -o strsep 21 | ./strsep "to be or not to be or to be both" 22 | 23 | clean: 24 | rm -f *~ strargs strbasic strstr strsep 25 | 26 | -------------------------------------------------------------------------------- /libc_files/fblock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BUFFER_SIZE 1024 5 | 6 | int main(int argc, char* argv[]) { 7 | 8 | /* open file, exit if fail */ 9 | FILE* file = fopen(argv[1], "r"); 10 | if ( file == NULL ) { 11 | printf("error: could not open %s\n", argv[1]); 12 | exit(EXIT_FAILURE); // ends the program 13 | } 14 | 15 | /* read file, print it to terminal */ 16 | int nchars; 17 | char buffer[BUFFER_SIZE]; 18 | while ( (nchars = fread(buffer, sizeof(char), BUFFER_SIZE, file)) != 0 ) 19 | fwrite(buffer, sizeof(char), nchars, stdout); 20 | 21 | /* close file */ 22 | fclose(file); 23 | 24 | /* return gracefully */ 25 | exit(EXIT_SUCCESS); 26 | } 27 | -------------------------------------------------------------------------------- /libc_files/getline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | ssize_t read; 7 | size_t size = 0; 8 | char* line = NULL; 9 | 10 | /* open file, exit if fail */ 11 | FILE* file = fopen(argv[1], "r"); 12 | if ( file == NULL ) { 13 | printf("error: could not open %s\n", argv[1]); 14 | exit(EXIT_FAILURE); // ends the program 15 | } 16 | 17 | /* read file, line by line */ 18 | int lineno = 1; 19 | while ((read = getline(&line, &size, file)) != -1) { 20 | printf("[%5d]: %s", lineno, line); 21 | lineno++; 22 | } 23 | 24 | /* close file */ 25 | fclose(file); 26 | 27 | /* return gracefully */ 28 | exit(EXIT_SUCCESS); 29 | } 30 | -------------------------------------------------------------------------------- /libc_files/fchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | 6 | /* open file, exit if fail */ 7 | FILE* file = fopen(argv[1], "r"); 8 | if ( file == NULL ) { 9 | printf("error: could not open %s\n", argv[1]); 10 | exit(EXIT_FAILURE); // ends the program 11 | } 12 | 13 | /* read file, char by char, print to terminal */ 14 | char c; 15 | int nchars = 0; 16 | while ( (c = fgetc(file)) != EOF ) { 17 | printf("%c", c); 18 | nchars++; 19 | } 20 | printf("-----------------------\n"); 21 | printf("total chars: %d\n", nchars); 22 | printf("-----------------------\n"); 23 | 24 | /* close file */ 25 | fclose(file); 26 | 27 | /* return gracefully */ 28 | exit(EXIT_SUCCESS); 29 | } 30 | -------------------------------------------------------------------------------- /syscalls_proc/forkexecl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char* argv[]) { 8 | pid_t pid; 9 | 10 | /* fork a child process */ 11 | if ((pid = fork()) < 0 ) { 12 | printf("%s: cannot fork()\n", argv[0]); 13 | exit(EXIT_FAILURE); 14 | } else if (pid == 0) { 15 | /* child process */ 16 | if (execlp(argv[1],argv[1],NULL) < 0) { 17 | printf("failed to exec %s\n", argv[1]); 18 | exit(EXIT_FAILURE); 19 | } 20 | } else { 21 | /* parent process */ 22 | if (waitpid(pid, NULL, 0) < 0) { 23 | printf("%s: cannot wait for child\n", argv[0]); 24 | exit(EXIT_FAILURE); 25 | } 26 | } 27 | exit(EXIT_SUCCESS); 28 | } 29 | -------------------------------------------------------------------------------- /lib_complex/complex.h: -------------------------------------------------------------------------------- 1 | /* definition of new type complex */ 2 | typedef 3 | struct { 4 | double x; 5 | double y; 6 | } 7 | complex; 8 | 9 | /* definition of the complex API */ 10 | complex complex_new(double, double); 11 | char* complex_print(complex); 12 | 13 | complex complex_add(complex, complex); 14 | complex complex_sub(complex, complex); 15 | complex complex_mul(complex, complex); 16 | complex complex_div(complex, complex); 17 | complex complex_conj(complex); 18 | 19 | double complex_mod(complex); 20 | double complex_arg(complex); 21 | double complex_re(complex); 22 | double complex_im(complex); 23 | 24 | complex complex_exp(complex); 25 | complex complex_log(complex); 26 | complex complex_sin(complex); 27 | complex complex_cos(complex); 28 | complex complex_tan(complex); 29 | complex complex_cot(complex); 30 | 31 | -------------------------------------------------------------------------------- /syscalls_proc/forkaddr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int value = 0; 8 | 9 | int main(int argc, char* argv[]) { 10 | pid_t pid; 11 | 12 | if ((pid = fork()) < 0 ) { 13 | printf("%s: cannot fork()\n", argv[0]); 14 | exit(EXIT_FAILURE); 15 | } 16 | else if (pid == 0) { 17 | /* child process */ 18 | value = 1; 19 | printf("value@child = %d, value address = %p\n",value,&value); 20 | exit(EXIT_SUCCESS); 21 | } else { 22 | /* parent process */ 23 | if (waitpid(pid, NULL, 0) < 0) { 24 | printf("%s: cannot wait for child\n", argv[0]); 25 | exit(EXIT_FAILURE); 26 | } 27 | printf("value@parent = %d, value address = %p\n",value,&value); 28 | exit(EXIT_SUCCESS); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /syscalls_files/fdir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main (int argc, char** argv) { 6 | 7 | /* check if argument is given */ 8 | if (argc != 2) { 9 | fprintf (stderr, "usage: %s dirname\n", argv[0]); 10 | exit(EXIT_FAILURE); 11 | } 12 | 13 | /* try to open directory */ 14 | DIR* q = opendir (argv[1]); 15 | if (q == NULL) { 16 | fprintf (stderr, "%s: Cannot open directory '%s'\n", argv[0], argv[1]); 17 | exit(EXIT_FAILURE); 18 | } 19 | 20 | /* list contents of directory */ 21 | printf ("%s/\n", argv[1]); 22 | struct dirent* p = readdir(q); 23 | while (p != NULL) { 24 | printf ("\t%s\n", p->d_name); 25 | p = readdir(q); 26 | } 27 | 28 | /* close directory */ 29 | closedir (q); 30 | 31 | /* return gracefully */ 32 | exit(EXIT_SUCCESS); 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project provides basic C source code examples, build commands and input files 2 | for common use cases of libC and kernel API functions. 3 | 4 | | directory | description | 5 | | :------------- | :------------------------------------------------------------------------------ | 6 | | data_files | data files for testing | 7 | | lib_complex | complex number static and dynamic libraries | 8 | | libc_strings | using libc functions for manipulating strings | 9 | | libc_files | using libc functions for manipulating files | 10 | | syscalls_files | using the kernel API for files and dirs | 11 | | syscalls_proc | using the kernel API for process management | 12 | | syscalls_ipc | using the kernel API for shared memory, pipes and sockets | 13 | | syscalls_sig | using the kernel and libc APIs for signals | 14 | 15 | 16 | 17 | (copyleft Luís Lopes) 18 | -------------------------------------------------------------------------------- /lib_complex/use_complex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "complex.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | complex z1 = complex_new(-2.16793, 5.23394); 7 | complex z2 = complex_new( 2.16793, -2.52236); 8 | complex z3 = complex_add(z1, z2); 9 | complex z4 = complex_sub(z1, z2); 10 | complex z5 = complex_mul(z1, z2); 11 | complex z6 = complex_div(z1, z2); 12 | double x1 = complex_mod(z1); 13 | double x2 = complex_re(z1); 14 | double x3 = complex_im(z3); 15 | printf("z1 = %s\n", complex_print(z1)); 16 | printf("z2 = %s\n", complex_print(z2)); 17 | printf("z3 = %s\n", complex_print(z3)); 18 | printf("z4 = %s\n", complex_print(z4)); 19 | printf("z5 = %s\n", complex_print(z5)); 20 | printf("z6 = %s\n", complex_print(z6)); 21 | printf("x1 = %f\n", x1); 22 | printf("x2 = %f\n", x2); 23 | printf("x3 = %f\n", x3); 24 | exit(EXIT_SUCCESS); 25 | } 26 | -------------------------------------------------------------------------------- /syscalls_files/fbasic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main(int argc, char* argv[]) { 11 | 12 | /* check if exactly one argument is present */ 13 | if(argc != 2) { 14 | printf("usage: cat filename\n"); 15 | exit(EXIT_FAILURE); 16 | } 17 | 18 | /* check if file can be opened and is readable */ 19 | int fd = open(argv[1], O_RDONLY); 20 | if(fd == -1) { 21 | printf("error: cannot open %s\n", argv[1]); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | /* read contents in blocks and print to terminal */ 26 | int nbytes; 27 | char buffer[BUFFER_SIZE]; 28 | while( (nbytes = read(fd, buffer, BUFFER_SIZE)) != 0 ) 29 | write(STDOUT_FILENO, buffer, nbytes); 30 | 31 | /* close file */ 32 | close(fd); 33 | 34 | /* return gracefully */ 35 | exit(EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /libc_strings/strargs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) { 6 | 7 | printf("command %s has %d arguments\n", argv[0], argc-1); 8 | 9 | for(int i = 1 ; i < argc ; i++) 10 | printf("argv[%d]: %s\n",i,argv[i]); 11 | 12 | for( int i = 1 ; i < argc ; /* in body */ ) { 13 | if( strcmp(argv[i], "-l") == 0 ) { 14 | printf("l-option, valid arg: %s\n", argv[i]); 15 | i += 1; 16 | } 17 | else 18 | if( strcmp(argv[i], "-u") == 0 ) { 19 | printf("u-option, valid arg: %s\n", argv[i]); 20 | i += 1; 21 | } 22 | else 23 | if( strcmp(argv[i], "-f") == 0 ) { 24 | printf("f-option, valid arg: %s, file is: %s\n", argv[i], argv[i+1]); 25 | i += 2; 26 | } 27 | else { 28 | printf("invalid arg: %s, usage: ./test [-l|-u] -f file\n", argv[i]); 29 | exit(EXIT_FAILURE); 30 | } 31 | } 32 | exit(EXIT_SUCCESS); 33 | } 34 | -------------------------------------------------------------------------------- /syscalls_sig/sigtimer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void read_sensor(int signum) { 7 | printf("calling sensor reading function\n"); 8 | } 9 | 10 | int main (int argc, char* argv[]) { 11 | struct sigaction action; 12 | struct itimerval timer; 13 | 14 | /* install timer_handler as the signal handler for SIGVTALRM. */ 15 | memset (&action, 0, sizeof (action)); 16 | action.sa_handler = &read_sensor; 17 | sigaction (SIGVTALRM, &action, NULL); 18 | 19 | /* configure the timer to expire after 2.5 seconds */ 20 | timer.it_value.tv_sec = 2; 21 | timer.it_value.tv_usec = 500000; 22 | 23 | /* and every 2.5 seconds after that */ 24 | timer.it_interval.tv_sec = 2; 25 | timer.it_interval.tv_usec = 500000; 26 | 27 | /* 28 | * start the timer 29 | * it counts down whenever this process is executing. 30 | */ 31 | setitimer (ITIMER_VIRTUAL, &timer, NULL); 32 | 33 | /* Do busy work. */ 34 | for( ; ; ) 35 | ; 36 | } 37 | -------------------------------------------------------------------------------- /lib_complex/libcomplex_howto.txt: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To build the static library libcomplex.a: 4 | 5 | $ make liba 6 | 7 | To build the dynamic library (shared object) libcomplex.so: 8 | 9 | $ make libd 10 | 11 | To make the case study usage example: 12 | 13 | $ make use 14 | 15 | To remove temporary files, the libraries and the executable 16 | 17 | $ make clean 18 | 19 | IMPORTANT NOTE: 20 | if you are using the dynamic library "libcomplex.so" 21 | before running "use_complex" for the first time 22 | you must run the following shell command: 23 | 24 | $ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH 25 | 26 | LD_LIBRARY_PATH is a shell variable that, similarly to PATH, 27 | contains a list of ":" separated directories that show the 28 | operating system where to find the ".so" files at runtime. 29 | The above command adds the current directory "." to that list. 30 | 31 | *********************************************************** 32 | -------------------------------------------------------------------------------- /syscalls_proc/syscallsproc.howto: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To build all (examples: fork, wait, execl, execvp) 4 | 5 | $ make 6 | 7 | or 8 | 9 | $ make all 10 | 11 | To remove temporary files and executable 12 | 13 | $ make clean 14 | 15 | 16 | Use the commands as follows: 17 | 18 | $ ./forkseq 19 | 20 | $ ./forkfor 21 | 22 | $ ./forkaddr 23 | 24 | $ ./forkexecl "ls" 25 | $ ./forkexecl "pwd" 26 | $ ./forkexecl "ls -l" # note "ls -l" will not be executed correctly 27 | 28 | $ ./shexecl 29 | > ls # your shell now! 30 | ... 31 | > pwd 32 | ... 33 | > ls -l # note "ls -l" will not be executed correctly 34 | ... 35 | > ps -A # note "ps -A" will not be executed correctly 36 | ... 37 | > quit 38 | 39 | $ ./shexecvp 40 | > ls # your shell now! 41 | ... 42 | > pwd 43 | ... 44 | > ls -l # works correctly now 45 | ... 46 | > ps -A # works correctly now 47 | ... 48 | > quit 49 | $ # back to terminal shell 50 | 51 | *********************************************************** 52 | -------------------------------------------------------------------------------- /syscalls_sig/signals.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static void handler1() { printf("received SIGUSR1\n"); } 9 | 10 | static void handler2() { printf("received SIGUSR2\n"); } 11 | 12 | static void handler3() { printf("received SIGHUP\n"); } 13 | 14 | static void handler4() { printf("received SIGINT\n"); } 15 | 16 | int main(int argc, char* argv[]) { 17 | printf("My PID is %d\n", getpid()); 18 | if (signal(SIGUSR1, handler1) == SIG_ERR) { 19 | fprintf(stderr, "Can't catch SIGUSR1: %s", strerror(errno)); 20 | exit(EXIT_FAILURE); 21 | } 22 | if (signal(SIGUSR2, handler2) == SIG_ERR) { 23 | fprintf(stderr, "Can't catch SIGUSR2: %s", strerror(errno)); 24 | exit(EXIT_FAILURE); 25 | } 26 | if (signal(SIGHUP, handler3) == SIG_ERR) { 27 | fprintf(stderr, "Can't catch SIGHUP: %s", strerror(errno)); 28 | exit(EXIT_FAILURE); 29 | } 30 | if (signal(SIGINT, handler4) == SIG_ERR) { 31 | fprintf(stderr, "Can't catch SIGINT: %s", strerror(errno)); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | /* stick around ... */ 36 | for ( ; ; ) 37 | pause(); 38 | } 39 | -------------------------------------------------------------------------------- /syscalls_files/fstat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char* argv[]) { 7 | 8 | /* check if argument is given */ 9 | if (argc != 2) { 10 | fprintf(stderr, "usage: %s file\n", argv[0]); 11 | exit(EXIT_FAILURE); 12 | } 13 | 14 | /* get file size & block info */ 15 | struct stat info; 16 | if (stat(argv[1], &info) == -1) { 17 | fprintf(stderr, "fsize: Can't stat %s\n", argv[1]); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | /* print file name, owner, size & block info */ 22 | printf("file name : %s\n", argv[1]); 23 | printf("owner uid : %d\n", (int)info.st_uid); 24 | printf("size : %d bytes\n", (int)info.st_size); 25 | printf("disk blocks : %d blocks\n", (int)info.st_blocks); 26 | 27 | /* last access, modification and status change times */ 28 | printf("last access : %s", ctime(&(info.st_atim.tv_sec))); 29 | printf("last data modification : %s", ctime(&(info.st_mtim.tv_sec))); 30 | printf("last file status change: %s", ctime(&(info.st_ctim.tv_sec))); 31 | 32 | /* return gracefully */ 33 | exit(EXIT_SUCCESS); 34 | } 35 | -------------------------------------------------------------------------------- /libc_strings/strbasic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * simple string manipulation: strdup, strcmp, strcpy, strcat 7 | */ 8 | 9 | int main(int argc, char* argv[]) { 10 | 11 | /* 12 | * compare argv[1] and argv[2] using lexicographic order 13 | */ 14 | int result = strcmp(argv[1], argv[2]); 15 | if (result == 0) 16 | printf("the strings are the same\n"); 17 | else if (result < 0) 18 | printf("%s < %s\n", argv[1], argv[2]); 19 | else 20 | printf("%s > %s\n", argv[1], argv[2]); 21 | 22 | /* 23 | * create a copy of argv[1] and another of argv[2] 24 | */ 25 | char *p1 = strdup(argv[1]); 26 | char *p2 = strdup(argv[2]); 27 | printf("p1 holds:%s\n", p1); 28 | printf("p2 holds:%s\n", p2); 29 | 30 | /* 31 | * this is another way of doing it 32 | */ 33 | char* p3 = (char*)malloc((strlen(argv[1]) + 1) * sizeof(char)); 34 | char* p4 = (char*)malloc((strlen(argv[2]) + 1) * sizeof(char)); 35 | strcpy(p3, argv[1]); 36 | strcpy(p4, argv[2]); 37 | printf("p3 holds:%s\n", p3); 38 | printf("p4 holds:%s\n", p4); 39 | 40 | /* 41 | * concatenate both strings, allocating space for: 42 | all chars of argv[1], 43 | all chars of argv[2], 44 | the final '\0' 45 | */ 46 | char* p5 = (char*)malloc((strlen(argv[1]) + strlen(argv[2]) + 1) * sizeof(char)); 47 | strcpy(p5, p1); 48 | strcat(p5, p2); 49 | printf("p5 holds:%s\n", p5); 50 | 51 | exit(EXIT_SUCCESS); 52 | } 53 | -------------------------------------------------------------------------------- /libc_files/getopt.c: -------------------------------------------------------------------------------- 1 | /* based on example from: 2 | * https://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int calculate_chars(char* filename) { 10 | //... 11 | printf("file: %s\n", filename); 12 | return 0; 13 | } 14 | 15 | int calculate_words(char* filename) { 16 | //... 17 | printf("file: %s\n", filename); 18 | return 0; 19 | } 20 | 21 | int calculate_lines(char* filename) { 22 | //... 23 | printf("file: %s\n", filename); 24 | return 0; 25 | } 26 | 27 | int main (int argc, char* argv[]) { 28 | int cflag = 0; 29 | int wflag = 0; 30 | int lflag = 0; 31 | 32 | opterr = 0; 33 | int c; 34 | while ((c = getopt (argc, argv, "cwl")) != -1) 35 | switch (c) { 36 | case 'c': 37 | cflag = 1; 38 | break; 39 | case 'w': 40 | wflag = 1; 41 | break; 42 | case 'l': 43 | lflag = 1; 44 | break; 45 | default: 46 | exit(EXIT_FAILURE); 47 | } 48 | 49 | char* filename = argv[optind]; 50 | if ( filename == NULL ) { 51 | printf("usage: %s [-c|-w|-l] file\n", argv[0]); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | 56 | if ( cflag ) 57 | printf("#chars: %d\n", calculate_chars(filename)); 58 | if ( wflag ) 59 | printf("#words: %d\n", calculate_words(filename)); 60 | if ( lflag ) 61 | printf("#lines: %d\n", calculate_lines(filename)); 62 | 63 | exit(EXIT_SUCCESS); 64 | } 65 | -------------------------------------------------------------------------------- /syscalls_ipc/syscallsipc.howto: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To build all (examples: fork, wait, pipe, socket) 4 | 5 | $ make 6 | 7 | or 8 | 9 | $ make all 10 | 11 | To remove temporary files and executable 12 | 13 | $ make clean 14 | 15 | Use the commands as follows 16 | 17 | [1] shared memory 18 | $ ./mmap ../data_files/matrix.txt 2 3 19 | 20 | 21 | [2] pipes 22 | $ ./pipe 23 | Hello child \(...\)! I\'m your parent pid \(...\). 24 | 25 | 26 | [3] sockets 27 | $ ./socket ../data_files/quote.txt 28 | Such is the nature of evil. 29 | Out there in the vast ignorance of the world it festers and spreads. 30 | A shadow that grows in the dark. 31 | A sleepless malice as black as the oncoming wall of night. 32 | So it ever was. 33 | So will it always be. 34 | In time all foul things come forth. 35 | -- Thranduil, Elven King 36 | 37 | For the final example, create two TABS or open 2 terminals 38 | 39 | @TAB1 40 | 41 | $ ./server 42 | 43 | @TAB2 44 | 45 | $ ./client 127.0.0.1 55901 ../data_files/quote.txt 46 | 47 | 48 | TAB1 output 49 | 50 | server listening at port 55901 # your port number will be different 51 | Such is the nature of evil. 52 | Out there in the vast ignorance of the world it festers and spreads. 53 | A shadow that grows in the dark. 54 | A sleepless malice as black as the oncoming wall of night. 55 | So it ever was. 56 | So will it always be. 57 | In time all foul things come forth. 58 | -- Thranduil, Elven King 59 | 60 | *********************************************************** -------------------------------------------------------------------------------- /syscalls_ipc/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUF_SIZE 1024 9 | 10 | /* 11 | * this is the server side 12 | */ 13 | 14 | int main(int argc, char* argv[]) { 15 | int sock; 16 | socklen_t length; 17 | struct sockaddr_in name; 18 | 19 | /* create socket from which to read */ 20 | if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 21 | perror("opening datagram socket"); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | /* create name with wildcards - port will be given by OS */ 26 | name.sin_family = AF_INET; 27 | name.sin_addr.s_addr = INADDR_ANY; 28 | name.sin_port = 0; 29 | if (bind(sock, (struct sockaddr *)&name, sizeof(name))) { 30 | perror("binding datagram socket"); 31 | exit(EXIT_FAILURE); 32 | } 33 | 34 | /* find assigned port value and print it out */ 35 | length = (socklen_t)sizeof(name); 36 | if (getsockname(sock, (struct sockaddr *)&name, &length)) { 37 | perror("getting socket name"); 38 | exit(EXIT_FAILURE); 39 | } 40 | printf("server listening at port %d\n", ntohs(name.sin_port)); 41 | printf("..............................\n"); 42 | 43 | /* read eternally from the socket */ 44 | int nbytes; 45 | char buf[BUF_SIZE]; 46 | for( ; ; ) 47 | while ((nbytes = read(sock, buf, BUF_SIZE)) > 0) { 48 | write(STDOUT_FILENO, buf, nbytes); 49 | printf("..............................\n"); 50 | } 51 | 52 | /* close socket - never gets here */ 53 | close(sock); 54 | 55 | /* return gracefully - never gets here */ 56 | exit(EXIT_SUCCESS); 57 | } 58 | -------------------------------------------------------------------------------- /syscalls_sig/sighup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* program parameters */ 10 | static int param1; 11 | static int param2; 12 | static float param3; 13 | static float param4; 14 | 15 | void read_parameters() { 16 | FILE *fp; 17 | 18 | if ( (fp = fopen(".config", "r")) == NULL ){ 19 | printf("Missing configuration file\n"); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | fscanf(fp, "param1: %d\n", ¶m1); 24 | fscanf(fp, "param2: %d\n", ¶m2); 25 | fscanf(fp, "param3: %f\n", ¶m3); 26 | fscanf(fp, "param4: %f\n", ¶m4); 27 | 28 | fclose(fp); 29 | } 30 | 31 | void print_parameters() { 32 | printf("param1: %d\n", param1); 33 | printf("param2: %d\n", param2); 34 | printf("param3: %f\n", param3); 35 | printf("param4: %f\n", param4); 36 | } 37 | 38 | /* 39 | * SIGHUP signals are caught and force process 40 | * to re-read configuration file and update 41 | * parameter values 42 | */ 43 | void handler (int signum) { 44 | read_parameters(); 45 | printf ("reading parameters, values are:\n"); 46 | print_parameters(); 47 | } 48 | 49 | int main (int argc, char* argv[]) { 50 | if (signal(SIGHUP, handler) == SIG_ERR) { 51 | fprintf(stderr, "Can't catch SIGHUP: %s", strerror(errno)); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | /* print PID for reference */ 56 | printf("my PID is %d\n", getpid()); 57 | 58 | /* read initial parameters */ 59 | read_parameters(); 60 | 61 | /* stick around and catch SIGHUP signals */ 62 | printf("working...\n"); 63 | for ( ; ; ) 64 | ; 65 | } 66 | -------------------------------------------------------------------------------- /syscalls_sig/syscallssig.howto: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | 3 | To build all (examples: sigaction, signal, alarm, kill) 4 | 5 | $ make 6 | 7 | or 8 | 9 | $ make all 10 | 11 | To remove temporary files and executable 12 | 13 | $ make clean 14 | 15 | Use the commands as follows 16 | 17 | **signals** 18 | 19 | $ ./signals & # & detaches ./signals from the Terminal 20 | My PID is 22402 # your PID will be different! 21 | $ kill -SIGUSR1 22402 22 | received SIGUSR1 23 | $ kill -SIGUSR2 22402 24 | received SIGUSR2 25 | $ kill -SIGHUP 22402 26 | received SIGHUP 27 | $ kill -SIGINT 22402 28 | received SIGINT 29 | $ fg # ./signals is connected to the Terminal again 30 | ^Creceived SIGINT 31 | ^Creceived SIGINT 32 | ^Creceived SIGINT # process is catching ^C = SIGINT 33 | ^Z 34 | $ kill -SIGKILL 22402 # SIGKILL cannot be caught, always kills process 35 | 36 | 37 | **sighup** 38 | 39 | $ cat > .config 40 | param1: 263 41 | param2: 7912 42 | param3: -2.651178 43 | param4: 5.222693 44 | ^D 45 | $ 46 | $ ./sighup & 47 | my PID is 36595 48 | working... 49 | $ 50 | $ kill -HUP 36595 51 | read parameters, values are: 52 | param1: 263 53 | param2: 7912 54 | param3: -2.651178 55 | param4: 5.222693 56 | $ 57 | $ emacs .config (change some values and save) 58 | $ 59 | $ kill -HUP 36595 60 | read parameters, values are: 61 | param1: 263 62 | param2: 321 63 | param3: -2.651178 64 | param4: 3.333895 65 | $ 66 | 67 | 68 | **sigtimer** 69 | 70 | $ ./sigtimer 71 | calling sensor reading function 72 | calling sensor reading function 73 | calling sensor reading function 74 | calling sensor reading function 75 | ... 76 | 77 | *********************************************************** 78 | -------------------------------------------------------------------------------- /syscalls_ipc/pipe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define READ_END 0 9 | #define WRITE_END 1 10 | #define BUF_SIZE 256 11 | 12 | int main(int argc, char* argv[]) { 13 | int fd[2]; 14 | pid_t pid; 15 | 16 | if (pipe(fd) < 0) { 17 | perror("pipe error"); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | if ((pid = fork()) < 0) { 22 | perror("fork error"); 23 | exit(EXIT_FAILURE); 24 | } 25 | else 26 | if (pid > 0) { 27 | int nbytes; 28 | char line[BUF_SIZE]; 29 | 30 | /* parent writes to pipe */ 31 | close(fd[READ_END]); 32 | snprintf(line, BUF_SIZE, 33 | "Hello child (%d)! I'm your parent pid (%d).\n", 34 | pid, getpid()); 35 | if ((nbytes = write(fd[WRITE_END], line, strlen(line))) < 0) { 36 | fprintf(stderr, "Unable to write to pipe: %s\n", strerror(errno)); 37 | exit(EXIT_FAILURE); 38 | } 39 | close(fd[WRITE_END]); 40 | 41 | /* wait for child and exit */ 42 | if ( waitpid(pid, NULL, 0) < 0) { 43 | fprintf(stderr, "Unable to catch child exiting: %s\n", strerror(errno)); exit(EXIT_FAILURE); 44 | } 45 | 46 | /* return gracefully */ 47 | exit(EXIT_SUCCESS); 48 | } 49 | else { 50 | int nbytes; 51 | char line[BUF_SIZE]; 52 | 53 | /* child reads from pipe */ 54 | close(fd[WRITE_END]); 55 | if ((nbytes = read(fd[READ_END], line, BUF_SIZE)) < 0 ) { 56 | fprintf(stderr, "Unable to read from pipe: %s\n", strerror(errno)); 57 | exit(EXIT_FAILURE); 58 | } 59 | close(fd[READ_END]); 60 | 61 | /* write message from parent */ 62 | write(STDOUT_FILENO, line, nbytes); 63 | 64 | /* return gracefully */ 65 | exit(EXIT_SUCCESS); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /syscalls_ipc/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define BUF_SIZE 1024 12 | 13 | /* 14 | * this is the client side 15 | */ 16 | 17 | int main(int argc, char *argv[]) { 18 | int sock; 19 | struct sockaddr_in name; 20 | struct hostent *hp; 21 | 22 | /* check for at least one argument */ 23 | if (argc < 4) { 24 | printf("usage: %s hostname port file\n", argv[0]); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | /* create socket on which to send */ 29 | if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 30 | perror("opening datagram socket"); 31 | exit(EXIT_FAILURE); 32 | } 33 | 34 | /* destination is constructed from hostname 35 | and port both given in the command line */ 36 | if ((hp = gethostbyname(argv[1])) == 0) { 37 | fprintf(stderr, "%s: unknown host\n", argv[1]); 38 | exit(EXIT_FAILURE); 39 | } 40 | memcpy(&name.sin_addr, hp->h_addr, hp->h_length); 41 | name.sin_family = AF_INET; 42 | name.sin_port = htons(atoi(argv[2])); 43 | 44 | /* connect to given port */ 45 | if(connect(sock, (struct sockaddr *)&name, sizeof(name)) < 0) { 46 | perror("connecting to server socket"); 47 | exit(EXIT_FAILURE); 48 | } 49 | 50 | int fd = open(argv[3],O_RDONLY); 51 | 52 | /* read from file and write to socket */ 53 | int nbytes = 0; 54 | char buf[BUF_SIZE]; 55 | while((nbytes = read(fd,buf,BUF_SIZE)) > 0) { 56 | if (write(sock, buf, nbytes) < 0) { 57 | perror("sending datagram message"); 58 | exit(EXIT_FAILURE); 59 | } 60 | } 61 | 62 | /* close socket */ 63 | close(sock); 64 | 65 | /* return gracefully */ 66 | exit(EXIT_SUCCESS); 67 | } 68 | -------------------------------------------------------------------------------- /syscalls_proc/shexecl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 10 | * a simple shell: parent presents prompt, reads command, 11 | * forks a new process and tries to execlp the command. The 12 | * parent waits for the command to end and gives the prompt 13 | * again. 14 | */ 15 | 16 | int main(int argc, char** argv) { 17 | 18 | /* do this forever */ 19 | for( ; ; ) { 20 | char* command = NULL; 21 | size_t commcap = 0; 22 | 23 | /* give prompt, read command and null terminate it */ 24 | fprintf(stdout, "> "); 25 | if( getline(&command, &commcap, stdin) <= 0 ) 26 | break; 27 | command[strlen(command) - 1] = '\0'; 28 | /* prompt again if empty */ 29 | if( strcmp(command, "") == 0 ) 30 | continue; 31 | /* exit if command is quit */ 32 | if( strcmp(command, "quit") == 0 ) 33 | break; 34 | 35 | /* call fork and check return value */ 36 | pid_t pid; 37 | int status; 38 | if((pid = fork()) < 0) { 39 | fprintf(stderr, "%s: can't fork command: %s\n", 40 | argv[0], strerror(errno)); 41 | continue; 42 | } else if(pid == 0) { 43 | /* child only */ 44 | execlp(command, command, (char *)0); 45 | /* if I get here "execl" failed */ 46 | fprintf(stderr, "%s: couldn't exec %s: %s\n", 47 | argv[0], command, strerror(errno)); 48 | /* terminate with error to be caught by parent */ 49 | exit(EXIT_FAILURE); 50 | } 51 | 52 | /* shell waits for command to finish before giving prompt again */ 53 | if ((pid = waitpid(pid, &status, 0)) < 0) 54 | fprintf(stderr, "%s: waitpid error: %s\n", 55 | argv[0], strerror(errno)); 56 | } 57 | /* get here with a ^C and ^D */ 58 | exit(EXIT_SUCCESS); 59 | } 60 | -------------------------------------------------------------------------------- /syscalls_proc/shexecvp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define MAX_ARGS 16 10 | 11 | void get_args(char* command, char** args) { 12 | char* p; 13 | int i = 0; 14 | while ( (p = strsep(&command, " ")) != NULL) 15 | args[i++] = strdup(p); 16 | args[i] = NULL; 17 | } 18 | 19 | int main(int argc, char* argv[]) { 20 | 21 | /* do this until you get a ^C or a ^D */ 22 | for( ; ; ) { 23 | char* command = NULL; 24 | size_t commcap = 0; 25 | char* args[MAX_ARGS]; 26 | 27 | /* give prompt, read command and null terminate it */ 28 | fprintf(stdout, "> "); 29 | if( getline(&command, &commcap, stdin) <= 0) 30 | break; 31 | command[strlen(command) - 1] = '\0'; 32 | /* prompt again if empty */ 33 | if( strcmp(command, "") == 0 ) 34 | continue; 35 | /* exit if command is quit */ 36 | if( strcmp(command, "quit") == 0 ) 37 | break; 38 | 39 | /* call fork and check return value */ 40 | pid_t pid; 41 | if((pid = fork()) < 0) { 42 | fprintf(stderr, "%s: can't fork command: %s\n", 43 | argv[0], strerror(errno)); 44 | exit(EXIT_FAILURE); 45 | } 46 | else if(pid == 0) { 47 | /* break the command into tokens for execvp */ 48 | get_args(command, args); 49 | /* run execvp */ 50 | execvp(args[0], args); 51 | /* if I get here "execvp" failed */ 52 | fprintf(stderr, "%s: %s\n", argv[0], strerror(errno)); 53 | /* terminate with error to be caught by parent */ 54 | exit(EXIT_FAILURE); 55 | } 56 | 57 | /* shell waits for command to finish before giving prompt again */ 58 | if ((pid = waitpid(pid, NULL, 0)) < 0) { 59 | fprintf(stderr, "%s: %s\n", argv[0], strerror(errno)); 60 | exit(EXIT_FAILURE); 61 | } 62 | exit(EXIT_SUCCESS); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /syscalls_ipc/socket.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SOCK0 0 9 | #define SOCK1 1 10 | #define BUF_SIZE 1024 11 | 12 | 13 | /* 14 | * parent reads a file 15 | * parent writes file to socket 16 | * child reads file from socket 17 | * child writes file back to socket 18 | * parent reads file back from socket 19 | * parent prints file to terminal 20 | * file -> parent -> child -> parent -> terminal 21 | */ 22 | 23 | int main(int argc, char* argv[]) { 24 | int sockets[2]; 25 | pid_t pid; 26 | 27 | if (argc < 2) { 28 | printf("usage: %s file\n", argv[0]); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { 33 | perror("opening stream socket pair"); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | if ((pid = fork()) < 0) { 38 | perror("fork"); 39 | exit(EXIT_FAILURE); 40 | } 41 | else 42 | if (pid == 0) { 43 | int nbytes = 0; 44 | char buf[BUF_SIZE]; 45 | 46 | /* read content from socket, write same content to socket */ 47 | close(sockets[SOCK0]); 48 | while ((nbytes = read(sockets[SOCK1],buf,BUF_SIZE)) > 0) 49 | write(sockets[SOCK1],buf,nbytes); 50 | close(sockets[SOCK1]); 51 | 52 | /* return gracefully */ 53 | exit(EXIT_SUCCESS); 54 | } 55 | else { 56 | int nbytes = 0; 57 | char buf[BUF_SIZE]; 58 | 59 | /* this is the parent */ 60 | close(sockets[SOCK1]); 61 | int fd = open(argv[1],O_RDONLY); 62 | 63 | /* read from socket and write to stdout */ 64 | while((nbytes = read(fd,buf,BUF_SIZE)) > 0) { 65 | if (write(sockets[SOCK0],buf,nbytes) < 0) { 66 | perror("writing message"); 67 | } 68 | if (( nbytes = read(sockets[SOCK0],buf,BUF_SIZE)) > 0) { 69 | write(STDOUT_FILENO,buf,nbytes); 70 | } 71 | } 72 | close(sockets[SOCK0]); 73 | 74 | /* wait for child and exit */ 75 | if (waitpid(pid, NULL, 0) < 0) { 76 | perror("did not catch child exiting"); 77 | exit(EXIT_FAILURE); 78 | } 79 | 80 | /* return gracefully */ 81 | exit(EXIT_SUCCESS); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /syscalls_ipc/mmap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | int main(int argc, char *argv[]) { 9 | 10 | /* ------ create and read matrix ------ */ 11 | char* infile = argv[1]; 12 | int nprocs = atoi(argv[2]); 13 | int threshold = atoi(argv[3]); 14 | 15 | FILE *fp; 16 | if((fp = fopen(infile,"r")) == NULL){ 17 | perror("cannot open file"); 18 | exit(EXIT_FAILURE); 19 | } 20 | size_t str_size = 0; 21 | char* str = NULL; 22 | getline(&str, &str_size, fp); 23 | int n = atoi(str); 24 | int matrix[n][n]; 25 | int i = 0, j = 0; 26 | while ( getline(&str, &str_size, fp) > 0 ) { 27 | char* token = strtok(str," "); 28 | while( token != NULL ) { 29 | matrix[i][j]=atoi(token); 30 | token=strtok(NULL," "); 31 | j++; 32 | } 33 | i++; 34 | j=0; 35 | } 36 | fclose(fp); 37 | 38 | for(i = 0; i < n; i++){ 39 | for(j = 0; j < n; j++){ 40 | printf("%d ", matrix[i][j]); 41 | } 42 | printf("\n"); 43 | } 44 | 45 | /* ------ setup shared memory ------ */ 46 | 47 | int *partials = mmap(NULL, nprocs*sizeof(int), PROT_READ|PROT_WRITE, 48 | MAP_SHARED|MAP_ANONYMOUS, 0, 0); 49 | 50 | if(partials == MAP_FAILED){ 51 | perror("mmap"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | for(i = 0; i < nprocs; i++) 56 | partials[i] = 0; 57 | 58 | /* ------ start nprocs and do work ------ */ 59 | 60 | for(i = 0; i < nprocs; i++) { 61 | pid_t pid; 62 | if ((pid = fork()) < 0) { 63 | perror("fork"); 64 | exit(EXIT_FAILURE); 65 | } 66 | if(pid == 0) { 67 | for(int j = 0; j < n; j++) 68 | if(j % nprocs == i) 69 | for(int k = 0; k < n; k++) 70 | if(matrix[j][k] > threshold) 71 | partials[i]++; 72 | exit(EXIT_SUCCESS); 73 | } 74 | } 75 | 76 | /* ------ wait for nprocs to finish ------- */ 77 | for(i = 0; i < nprocs; i++) { 78 | if ( waitpid(-1, NULL, 0) < 0) { 79 | perror("waitpid"); 80 | exit(EXIT_FAILURE); 81 | } 82 | } 83 | 84 | /* ler resultados enviados pelos processos filhos */ 85 | int total = 0; 86 | for(i = 0; i < nprocs; i++) 87 | total += partials[i]; 88 | printf("%d\n",total); 89 | 90 | /* ------ release shared memory ------ */ 91 | if (munmap(partials, sizeof(partials)) < 0) { 92 | perror("munmap"); 93 | exit(EXIT_FAILURE); 94 | } 95 | 96 | exit(EXIT_SUCCESS); 97 | } 98 | -------------------------------------------------------------------------------- /lib_complex/complex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "complex.h" 6 | 7 | complex complex_new(double x, double y) { 8 | complex z; 9 | z.x = x; 10 | z.y = y; 11 | return z; 12 | } 13 | 14 | complex complex_add(complex z, complex w) { 15 | complex r; 16 | r.x = z.x + w.x; 17 | r.y = z.y + w.y; 18 | return r; 19 | } 20 | 21 | complex complex_sub(complex z, complex w) { 22 | complex r; 23 | r.x = z.x - w.x; 24 | r.y = z.y - w.y; 25 | return r; 26 | } 27 | 28 | complex complex_mul(complex z, complex w) { 29 | complex r; 30 | r.x = z.x * w.x - z.y * w.y; 31 | r.y = z.x * w.y + z.y * w.x; 32 | return r; 33 | } 34 | 35 | complex complex_div(complex z, complex w) { 36 | complex r; 37 | double d = w.x * w.x + w.y * w.y; 38 | r.x = ( z.x * w.x + z.y * w.y) / d; 39 | r.y = (- z.x * w.y + z.y * w.x) / d; 40 | return r; 41 | } 42 | 43 | complex complex_conj(complex z) { 44 | complex r; 45 | r.x = z.x; 46 | r.y = -z.y; 47 | return r; 48 | } 49 | 50 | double complex_mod(complex z) { 51 | return sqrt(z.x * z.x + z.y * z.y); 52 | } 53 | 54 | double complex_arg(complex z) { 55 | return atan2(z.y, z.x); 56 | } 57 | 58 | double complex_re(complex z) { 59 | return z.x; 60 | } 61 | 62 | double complex_im(complex z){ 63 | return z.y; 64 | } 65 | 66 | complex complex_exp(complex z) { 67 | complex r; 68 | r.x = exp(z.x) * cos(z.y); 69 | r.y = exp(z.x) * sin(z.y); 70 | return r; 71 | } 72 | 73 | complex complex_log(complex z) { 74 | complex r; 75 | r.x = log(complex_mod(z)); 76 | r.y = complex_arg(z); 77 | return r; 78 | } 79 | 80 | complex complex_sin(complex z) { 81 | complex r; 82 | r.x = sin(z.x) * cosh(z.y); 83 | r.y = cos(z.x) * sinh(z.y); 84 | return r; 85 | } 86 | 87 | complex complex_cos(complex z) { 88 | complex r; 89 | r.x = cos(z.x) * cosh(z.y); 90 | r.y = - sin(z.x) * sinh(z.y); 91 | return r; 92 | } 93 | 94 | complex complex_tan(complex z) { 95 | return complex_div(complex_sin(z),complex_cos(z)); 96 | } 97 | 98 | complex complex_cot(complex z) { 99 | return complex_div(complex_cos(z),complex_sin(z)); 100 | } 101 | 102 | #define MAXCHARS 256 103 | static char buffer[MAXCHARS]; 104 | 105 | char* complex_print(complex z) { 106 | if (z.y == 0) 107 | sprintf(buffer, "%f", z.x); 108 | else if (z.x == 0) 109 | sprintf(buffer, "%fi", z.y); 110 | else if (z.y > 0) 111 | sprintf(buffer, "%f+%fi", z.x, z.y); 112 | else 113 | sprintf(buffer, "%f%fi", z.x, z.y); 114 | return buffer; 115 | } 116 | --------------------------------------------------------------------------------