├── procs ├── tempfile ├── savefile ├── permfile ├── simple_getpid.c ├── syscallC.c ├── myincludes.h ├── fork_experiment.c ├── exceptions.c ├── zomB.c ├── reparent.c ├── priority_ops.c ├── forkloop.c ├── simple_exec.c ├── Makefile ├── fork_and_termP.c ├── simple_fork.c ├── fork_and_termC.c ├── sched_priochange.c ├── syscall.s ├── loopy.c ├── sched_info.c ├── README ├── duper.c ├── sched_policychange.c └── shell.c ├── files ├── xyz ├── testfile ├── myincludes.h ├── Makefile ├── flocking.c ├── test2_link.c ├── pipecmd.c ├── redirect.c ├── readfile.c ├── README ├── usingdup.c ├── test_link.c ├── repeated_printf.c ├── flush.c ├── file_as_a_lock.c └── check-fileinfo.c ├── misc ├── Mmap-test-file ├── divbyzero.c ├── reading.c ├── x.c ├── touch_bad_memory.c ├── fact.c ├── y.c ├── Makefile ├── printpid.c ├── gtotd.c ├── sig.c ├── address.c ├── check-endian.c ├── timer_intr.c ├── mmap1.c ├── sig2.c ├── README ├── mallocing.c ├── eratosthenes.c ├── mmap-simple.c └── showlim.c ├── docs ├── build │ ├── hello_world.h │ ├── hello_world.c │ ├── printpid.c │ ├── README │ ├── Makefile2 │ ├── Makefile1 │ └── Makefile3 ├── simple-pipe-linux-commandline ├── README-submission-guidelines ├── macro-expressions.c └── gdb-sheet ├── ipc ├── sockets │ ├── simple_tcp_client.sh │ ├── simple_tcp_server.sh │ ├── commons.h │ ├── Makefile │ ├── README │ ├── tcp_client.c │ ├── unx_client.c │ ├── tcp_long_client.c │ ├── udp_client.c │ ├── udp_server.c │ ├── udp_echo_server.c │ ├── unx_server.c │ ├── tcp_server.c │ └── conc_server.c ├── named-pipes │ ├── common.h │ ├── Makefile │ ├── README │ ├── fifo-reader.c │ ├── fifo-writer.c │ └── fifo-re-wr.c ├── shm │ ├── common.h │ ├── Makefile │ ├── README │ ├── filler.c │ ├── reader.c │ └── shm_ctl.c ├── shm-posix │ ├── common.h │ ├── Makefile │ ├── README │ ├── reader.c │ ├── filler.c │ └── shm_ctl.c ├── mq-posix │ ├── Makefile │ ├── README │ └── mq_ctl.c ├── sem │ ├── teardown.sh │ ├── configs.h │ ├── safe_ops.h │ ├── setup.sh │ ├── Makefile │ ├── mysemops.h │ ├── safe_ops.c │ ├── mysemops.c │ ├── shm_consumer.c │ ├── README │ ├── shm_producer.c │ ├── sem_ctl.c │ └── shm_ctl.c ├── sem-posix │ ├── Makefile │ ├── README │ ├── sem_ctl.c │ └── pc.c ├── msgque │ ├── Makefile │ ├── common.h │ ├── README │ ├── msg_reader.c │ ├── msg_writer.c │ └── msg_ctl.c └── simple-pipe │ └── pipe.c ├── Makefile ├── memory ├── Makefile ├── README └── frameit.c ├── pthreads ├── safe_ops.h ├── safe_ops.c ├── simple.c ├── Makefile ├── update_balance.c ├── README ├── find_some_primes.c ├── update_balance_mutex.c ├── prod_con.c ├── find_some_primes_2r.c ├── find_some_primes_mutex.c ├── find_some_primes_cv.c └── find_some_primes_cv_many.c ├── README.md └── utils └── mymake /procs/tempfile: -------------------------------------------------------------------------------- 1 | Hellow World 2 | -------------------------------------------------------------------------------- /files/xyz: -------------------------------------------------------------------------------- 1 | ABCDEFGHIJ1234567890 2 | -------------------------------------------------------------------------------- /misc/Mmap-test-file: -------------------------------------------------------------------------------- 1 | ABCDEFGHIJ 2 | -------------------------------------------------------------------------------- /docs/build/hello_world.h: -------------------------------------------------------------------------------- 1 | #define NAME "Sreevatsa" 2 | -------------------------------------------------------------------------------- /procs/savefile: -------------------------------------------------------------------------------- 1 | This is the house that Jack built. 2 | -------------------------------------------------------------------------------- /ipc/sockets/simple_tcp_client.sh: -------------------------------------------------------------------------------- 1 | nc -v 127.0.0.1 8080 2 | -------------------------------------------------------------------------------- /procs/permfile: -------------------------------------------------------------------------------- 1 | Hellow World 2 | ouse that Jack built. 3 | -------------------------------------------------------------------------------- /ipc/named-pipes/common.h: -------------------------------------------------------------------------------- 1 | #define PIPENAME "/tmp/fifo1" 2 | 3 | -------------------------------------------------------------------------------- /ipc/sockets/simple_tcp_server.sh: -------------------------------------------------------------------------------- 1 | nc -v -l -s 127.0.0.1 -p 8080 2 | -------------------------------------------------------------------------------- /files/testfile: -------------------------------------------------------------------------------- 1 | this 2 | is 3 | the 4 | house 5 | that 6 | jack 7 | built 8 | -------------------------------------------------------------------------------- /misc/divbyzero.c: -------------------------------------------------------------------------------- 1 | void main(){ 2 | int z = 25; 3 | z = z/(z-z); 4 | } 5 | -------------------------------------------------------------------------------- /misc/reading.c: -------------------------------------------------------------------------------- 1 | #include 2 | void main(){ 3 | int n; 4 | scanf("%d",&n); 5 | } 6 | -------------------------------------------------------------------------------- /misc/x.c: -------------------------------------------------------------------------------- 1 | #include 2 | void main() { 3 | printf("Hello World\n"); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /misc/touch_bad_memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void main(){ 4 | int *z = NULL; 5 | *z=1000; 6 | } 7 | -------------------------------------------------------------------------------- /ipc/shm/common.h: -------------------------------------------------------------------------------- 1 | #define SHM_KEY 9999 2 | #define MAX 100 3 | struct mystruct { 4 | int count; 5 | int val[MAX]; 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /ipc/shm-posix/common.h: -------------------------------------------------------------------------------- 1 | #define SHM_NAME "/ex1" 2 | #define MAX 100 3 | struct mystruct { 4 | int count; 5 | int val[MAX]; 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /ipc/sockets/commons.h: -------------------------------------------------------------------------------- 1 | #define SRV_PORT 9999 2 | #define fillzero(X) memset(&X, 0, sizeof(X)) 3 | #define UNIX_SOCK_PATH "/tmp/unx_sock" 4 | -------------------------------------------------------------------------------- /ipc/mq-posix/Makefile: -------------------------------------------------------------------------------- 1 | EXECS= mq_ctl 2 | 3 | all: $(EXECS) 4 | 5 | mq_ctl: mq_ctl.c 6 | gcc -o mq_ctl mq_ctl.c -lrt 7 | 8 | clean: 9 | rm -f $(EXECS) a.out 10 | -------------------------------------------------------------------------------- /procs/simple_getpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | 6 | 7 | void main(){ 8 | printf("My pid is: %d\n",getpid()); 9 | sleep(100); 10 | } 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | EXECS= simple pc 2 | 3 | help: 4 | echo USAGE: make all or make clean 5 | 6 | all: 7 | utils/mymake * 8 | 9 | 10 | 11 | clean: 12 | utils/mymake clean * 13 | -------------------------------------------------------------------------------- /docs/build/hello_world.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hello_world.h" 3 | 4 | int main(){ 5 | #ifndef NAME 6 | #define NAME "Ram" 7 | #endif 8 | 9 | printf("Hello dear %s\n",NAME); 10 | } 11 | -------------------------------------------------------------------------------- /ipc/sem/teardown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # remove the shared memory 3 | ./shm_ctl -r 8888 4 | 5 | # remove the three semaphores 777[765] 6 | ./sem_ctl -r 7777 7 | ./sem_ctl -r 7776 8 | ./sem_ctl -r 7775 9 | 10 | -------------------------------------------------------------------------------- /files/myincludes.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | -------------------------------------------------------------------------------- /ipc/sem-posix/Makefile: -------------------------------------------------------------------------------- 1 | EXECS= pc sem_ctl 2 | 3 | all: $(EXECS) 4 | 5 | 6 | pc: pc.c 7 | gcc -o pc pc.c -pthread 8 | 9 | sem_ctl: sem_ctl.c 10 | gcc -o sem_ctl sem_ctl.c -pthread 11 | 12 | 13 | clean: 14 | rm -f $(EXECS) a.out 15 | -------------------------------------------------------------------------------- /ipc/sem/configs.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_CONFIGS_DEFINED 2 | 3 | #define MY_CONFIGS_DEFINED 1 4 | 5 | #define SHM_KEY_VAL 8888 6 | #define SEM_KEY_VAL 7777 7 | #define SEM_KEY_EMPTY_SLOT 7776 8 | #define SEM_KEY_FILLED_SLOT 7775 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /procs/syscallC.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | char * message="hello from the C world\n"; 6 | 7 | void main() 8 | { 9 | syscall(SYS_write, 1, message , strlen(message)); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /memory/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | EXEC = frameit 3 | 4 | #OBJS = 5 | 6 | ##$(EXEC): 7 | 8 | all-execs: $(EXEC) 9 | 10 | all: all-execs 11 | 12 | 13 | clean: 14 | rm -f *.o a.out $(EXEC) 15 | 16 | help: 17 | echo all-execs/ all-objs /all /clean-all 18 | -------------------------------------------------------------------------------- /procs/myincludes.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | -------------------------------------------------------------------------------- /ipc/shm/Makefile: -------------------------------------------------------------------------------- 1 | EXECS= shm_ctl fl rd 2 | 3 | all: $(EXECS) 4 | 5 | shm_ctl: shm_ctl.c common.h 6 | gcc -o shm_ctl shm_ctl.c 7 | 8 | rd: reader.c common.h 9 | gcc -o rd reader.c 10 | 11 | fl: filler.c common.h 12 | gcc -o fl filler.c 13 | 14 | clean: 15 | rm -f $(EXECS) 16 | -------------------------------------------------------------------------------- /ipc/msgque/Makefile: -------------------------------------------------------------------------------- 1 | 2 | EXECS= rd wr ctl 3 | 4 | all: $(EXECS) 5 | 6 | ctl: msg_ctl.c common.h 7 | gcc -o ctl msg_ctl.c 8 | 9 | rd: msg_reader.c common.h 10 | gcc -o rd msg_reader.c 11 | 12 | wr: msg_writer.c common.h 13 | gcc -o wr msg_writer.c 14 | 15 | clean: 16 | rm -f $(EXECS) 17 | -------------------------------------------------------------------------------- /ipc/msgque/common.h: -------------------------------------------------------------------------------- 1 | // Needed for acquiring token via ftok: 2 | #define MYPROJECTPATH "/tmp/blah" 3 | #define MYPROJECTID 6764 4 | 5 | // Message structure definition: 6 | #define MSGSIZE 100 7 | #define TYPEA 1 8 | struct msgbuf { 9 | long mtype; 10 | char mtext[MSGSIZE]; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /misc/fact.c: -------------------------------------------------------------------------------- 1 | #include 2 | int fact(int n){ 3 | int x; 4 | if (n <= 1 ) 5 | return 1; 6 | else 7 | return n*fact(n-1); 8 | } 9 | int test(int y){ 10 | int x=1; 11 | int n = x + y; 12 | return n; 13 | } 14 | int main(){ 15 | int v=5; 16 | int f=test(v); 17 | int z=3; 18 | } 19 | -------------------------------------------------------------------------------- /ipc/shm-posix/Makefile: -------------------------------------------------------------------------------- 1 | EXECS= shm_ctl fl rd 2 | 3 | all: $(EXECS) 4 | 5 | shm_ctl: shm_ctl.c common.h 6 | gcc -o shm_ctl shm_ctl.c -lrt 7 | 8 | rd: reader.c common.h 9 | gcc -o rd reader.c -lrt 10 | 11 | fl: filler.c common.h 12 | gcc -o fl filler.c -lrt 13 | 14 | clean: 15 | rm -f $(EXECS) a.out 16 | -------------------------------------------------------------------------------- /misc/y.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(){ 7 | char * x ; 8 | printf("Here ---------------------> \n"); 9 | printf("Iam\n"); 10 | x = malloc(32767); 11 | x[10]='k'; 12 | } 13 | int fun(){ 14 | printf("Bye\n"); 15 | } 16 | -------------------------------------------------------------------------------- /procs/fork_experiment.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main(){ 5 | int x; int i=500; 6 | // printf("Have fun..."); 7 | x=fork(); 8 | if ( x == 0 ) { 9 | i++; 10 | printf("B i is %d at %p\n",i,&i); 11 | } else { 12 | i--; 13 | printf("C i is %d at %p\n",i,&i); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ipc/sem/safe_ops.h: -------------------------------------------------------------------------------- 1 | #define MAX 10 2 | 3 | struct mystruct { 4 | int val[MAX]; 5 | int free; 6 | int used; 7 | }; 8 | 9 | void put(int val, struct mystruct * s); 10 | int get(struct mystruct * s); 11 | void safely_put(int val, struct mystruct * s, int semid); 12 | int safely_get(struct mystruct * s, int semid); 13 | 14 | -------------------------------------------------------------------------------- /files/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | EXEC = check-fileinfo flush usingdup test_link test2_link \ 3 | file_as_a_lock readfile pipecmd redirect repeated_printf flocking 4 | 5 | all: $(EXEC) 6 | 7 | clean: 8 | rm -f a.out *.o $(EXEC) 9 | 10 | clean-objs: 11 | rm -f *.o 12 | 13 | help: 14 | echo all-execs/ all-objs /all /clean-all 15 | -------------------------------------------------------------------------------- /ipc/msgque/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | Simple message queue illustration 3 | 4 | FILES 5 | common.h : some common definitions 6 | msg_reader.c : to read from a message queue 7 | msg_writer.c : to write to a message queue 8 | msg_ctl.c : simple interface to create remove and print msgq info 9 | RUNNING 10 | ./rd 11 | ./wr 12 | ./msq_ctl -h 13 | -------------------------------------------------------------------------------- /misc/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | 3 | EXEC = check-endian printpid reading x y gtotd touch_bad_memory divbyzero address sig sig2 mmap1 mmap-simple showlim mallocing eratosthenes 4 | 5 | 6 | all: $(EXEC) 7 | 8 | clean: 9 | rm -f a.out *.o $(EXEC) 10 | 11 | clean-objs: 12 | rm -f *.o 13 | 14 | help: 15 | echo all-execs/ all-objs /all /clean-all 16 | -------------------------------------------------------------------------------- /misc/printpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | /* Simple program that executes (overlays) anoher program */ 13 | void main(){ 14 | printf("My PID = %d\n",(int)getpid()); 15 | } 16 | -------------------------------------------------------------------------------- /docs/build/printpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | /* Simple program that executes (overlays) anoher program */ 13 | void main(){ 14 | printf("My PID = %d\n",(int)getpid()); 15 | } 16 | -------------------------------------------------------------------------------- /ipc/named-pipes/Makefile: -------------------------------------------------------------------------------- 1 | 2 | EXECS= rd wr both 3 | 4 | all: $(EXECS) 5 | 6 | rd: fifo-reader.c common.h 7 | gcc -o rd fifo-reader.c 8 | 9 | wr: fifo-writer.c common.h 10 | gcc -o wr fifo-writer.c 11 | 12 | both: fifo-re-wr.c 13 | gcc -o both fifo-re-wr.c 14 | 15 | #just for fun 16 | fifo: 17 | mkfifo /tmp/fifo1 18 | 19 | clean: 20 | rm -f $(EXECS) a.out 21 | -------------------------------------------------------------------------------- /ipc/mq-posix/README: -------------------------------------------------------------------------------- 1 | ABOUT: 2 | A very simple example to show message queues can be used to trandfer messages 3 | between processes.... unlike pipes which is a stream of data. 4 | 5 | mq_ctl.c : The simple iterative controller program 6 | 7 | 8 | ./mq_ctl : Note that you need to read attrutes ( option 'a' ) 9 | before you can successfully receive ( option 'r' ) 10 | -------------------------------------------------------------------------------- /ipc/sem/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # setup the shared memory and initialize the free and used pointers 3 | ./shm_ctl -n 8888 4 | ./shm_ctl -i 8888 5 | 6 | # Make sure the three semaphores 777[765] exist and are initialize 7 | ./sem_ctl -n 7777; ./sem_ctl -i 7777 1 # (mutex) 8 | ./sem_ctl -n 7776; ./sem_ctl -i 7776 2 # (empty slots) 9 | ./sem_ctl -n 7775; ./sem_ctl -i 7775 0 # (filled slots) 10 | 11 | -------------------------------------------------------------------------------- /pthreads/safe_ops.h: -------------------------------------------------------------------------------- 1 | #define MAX 10 2 | 3 | struct mystruct { 4 | pthread_mutex_t mutex; 5 | int val[MAX]; 6 | int free; 7 | int used; 8 | }; 9 | 10 | #define ISEMPTY(s) (s.free==s.used) 11 | #define ISFULL(s) ((s.free+1)%MAX==s.used) 12 | 13 | void put(int val, struct mystruct * s); 14 | int get(struct mystruct * s); 15 | void safely_put(int val, struct mystruct * s, int semid); 16 | int safely_get(struct mystruct * s, int semid); 17 | 18 | -------------------------------------------------------------------------------- /ipc/shm/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | Simple shared memory example : no synchronisation etc :-) 3 | 4 | FILES 5 | filler.c Create a shared memory and fill data into it 6 | reader.c Read data written into shared memory 7 | shm_ctl.c Read info about an existing shared memory 8 | ./shm_ctl -h for more info on options 9 | common.h Some common definitions for the above files 10 | 11 | RUNNING 12 | make 13 | ./fl 14 | ./rd 15 | ./shm_ctl for some shm oprtations. 16 | -------------------------------------------------------------------------------- /procs/exceptions.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A program to generate some exceptions 3 | */ 4 | #include 5 | #define DIVBYZERO 1 6 | #define BADMEM 2 7 | #define BADACCESS 3 8 | const int x=0; 9 | void main(){ 10 | int type=3; 11 | switch( type ) { 12 | case DIVBYZERO: 13 | printf("div by zero: %d\n",type/(type-type)); 14 | case BADMEM: 15 | printf("bad mem: %d\n",*(int *)0x7fffffff); 16 | case BADACCESS: 17 | scanf("%d",&x); 18 | default: 19 | printf("Unknown, exit\n"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /misc/gtotd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* Simple program that executes (overlays) anoher program */ 14 | void main(){ 15 | struct timeval tv; struct timezone tz; 16 | printf("My PID = %d\n",(int)getpid()); 17 | gettimeofday(&tv,&tz); // To understand why this syscall is not seen see man vdso..... it shortcuts and reduces a syscall to a funciton call. 18 | } 19 | -------------------------------------------------------------------------------- /procs/zomB.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void main(int argc, char ** argv){ 5 | if (argc <= 1 ) printf("*Too few arguments: %s somename \n",argv[0]), 6 | exit(1); 7 | int r = fork(); 8 | if ( r < 0 ) { 9 | perror("Couldnt create new processes, exiting"); 10 | exit(1); 11 | } 12 | if ( r == 0) { 13 | // child simply exits 14 | exit(0); 15 | } else { 16 | // parent simply loops 17 | for (int i=0 ; i < 100 ; i ++) 18 | printf("%s\t%d \n",argv[1],i), 19 | sleep(1); 20 | } 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /procs/reparent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | void main(int argc, char ** argv){ 5 | if (argc <= 1 ) printf("*Too few arguments: %s somename \n",argv[0]), 6 | exit(1); 7 | int r = fork(); 8 | if ( r < 0 ) { 9 | perror("Couldnt create new processes, exiting"); 10 | exit(1); 11 | } 12 | if ( r != 0) { 13 | // parent simply exits 14 | exit(0); 15 | } else { 16 | // child simply loops 17 | for (int i=0 ; i < 100 ; i ++) 18 | printf("%s\t%d \n",argv[1],i), 19 | sleep(1); 20 | } 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /files/flocking.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | // syntax: int flock(int fd, int operation); 6 | // Valid values for operation are: LOCK_EX , LOCK_SH , LOCK_UN 7 | // return value is -1 if there is an error, 0 otherwise. See man flock(2) 8 | void main(){ 9 | int fd = open("xyz",O_RDONLY); 10 | flock(fd,LOCK_EX); 11 | int pid = getpid(); 12 | for(int i=0;i<9;i++) { 13 | printf("%d is using the lock\n",pid); 14 | for(int j=0;j 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int create_new_sem(int key) ; // Create a semaphore 8 | int get_existing_sem(int key) ; // get an exisittng semaphore 9 | void init_sem(int semind, int val); // Iniialize a semaphore 10 | int get_info_sem(int semid, struct semid_ds * buf); // getinfo 11 | int get_val_sem(int semid); // getinfo 12 | void remove_sem(int semid); // Remove semaphore from the system 13 | 14 | void lock_down(int semid); 15 | void free_up(int semid); 16 | 17 | -------------------------------------------------------------------------------- /ipc/sem-posix/README: -------------------------------------------------------------------------------- 1 | These examples are about named and unnamed posix semaphores 2 | 3 | pc.c : Has a number of threads as producers and consumers 4 | for a shared queue structure 5 | You can set NUMPRODUCERS/NUMCONSUMERS 6 | Also you can set size of the shared queue 7 | Note: There is a #define NAMED_SEM for chosing which type 8 | of semaphore 9 | If named semaphore is uses the semaphore is 10 | first removed before it initializes 11 | ./pc 12 | 13 | 14 | sem_ctl.c : This uses named semaphores. 15 | And illustrates basic operations. 16 | 17 | ./sem_ctl 18 | 19 | -------------------------------------------------------------------------------- /files/test2_link.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #define COMMAND(X) (strcmp(argv[1],X)==0) 10 | int main(int argc, char ** argv){ 11 | 12 | printf("%d\n", argc); 13 | for( int i = 0; i 2 | #include 3 | #include 4 | #include 5 | #include "safe_ops.h" 6 | 7 | void put(int val, struct mystruct * s){ 8 | s->val[s->free]=val; 9 | s->free=(s->free+1)%MAX; 10 | } 11 | int get(struct mystruct * s){ 12 | int x=s->val[s->used]; 13 | s->used=(s->used+1)%MAX; 14 | return x; 15 | } 16 | 17 | /* 18 | void safely_put(int val, struct mystruct * s, int semid){ 19 | lock_down(semid); 20 | put(val, s); 21 | free_up(semid); 22 | } 23 | 24 | int safely_get(struct mystruct * s, int semid){ 25 | lock_down(semid); 26 | int x = get(s); 27 | free_up(semid); 28 | return x; 29 | } 30 | */ 31 | -------------------------------------------------------------------------------- /misc/sig.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int g=99; 7 | 8 | void handler(int signo) { 9 | if (signo == SIGUSR1) 10 | printf("received SIGUSR1 when g=%d\n",g); 11 | g++; 12 | } 13 | 14 | void set_my_signal(){ 15 | if (signal(SIGUSR1, handler) == SIG_ERR) { 16 | perror("setting signal failed"); 17 | exit(1); 18 | } 19 | } 20 | int main() { 21 | set_my_signal(); 22 | printf("g is at %p\n",&g); 23 | int x=1; 24 | while(1) { 25 | sleep(1); 26 | for(int i=0;i 10 ) x=1; 30 | } 31 | printf("Finished g=%d\n",g); 32 | } 33 | -------------------------------------------------------------------------------- /ipc/sem/safe_ops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "configs.h" 6 | #include "safe_ops.h" 7 | #include "mysemops.h" 8 | 9 | void put(int val, struct mystruct * s){ 10 | s->val[s->free]=val; 11 | s->free=(s->free+1)%MAX; 12 | } 13 | int get(struct mystruct * s){ 14 | int x=s->val[s->used]; 15 | s->used=(s->used+1)%MAX; 16 | return x; 17 | } 18 | 19 | void safely_put(int val, struct mystruct * s, int semid){ 20 | lock_down(semid); 21 | put(val, s); 22 | free_up(semid); 23 | } 24 | 25 | int safely_get(struct mystruct * s, int semid){ 26 | lock_down(semid); 27 | int x = get(s); 28 | free_up(semid); 29 | return x; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /procs/priority_ops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | /* 6 | int getpriority(int which, id_t who); 7 | int setpriority(int which, id_t who, int prio); 8 | */ 9 | void main(){ 10 | int pid=getpid(); 11 | printf("My PID is %d\n",pid); 12 | int prio=getpriority(PRIO_PROCESS,pid); 13 | printf("My Priority is %d\n",prio); 14 | getchar(); 15 | printf("Setting my priority\n"); 16 | int r = setpriority(PRIO_PROCESS,pid, prio+4); 17 | if ( r == -1) 18 | printf("Error setting priority**\n"); 19 | prio=-99; 20 | prio=getpriority(PRIO_PROCESS,pid); 21 | printf("My Priority is %d\n",prio); 22 | getchar(); 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /ipc/named-pipes/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | The idea is to demonstrate the use of named pipes also called FIFOs 3 | 4 | FILES 5 | fifo-writer.c Opens and writes into a fifo 6 | fifo-reader.c Opens and reads from the fifo 7 | fifo-re-rw.c Opens for both reading and writing, done sequentially 8 | common.h The fifo is named here 9 | 10 | RUNNING 11 | Expt-1: 12 | mkfifo to create the fifo eg ./mkfifo /tmp/myfifo 13 | ./rd 14 | ./wr 15 | Expt-2: 16 | Independently try out: 17 | ./both 18 | 19 | Some experiments: 20 | 1. Change the writer's sleep value (or remove it) 21 | 2. Just for fun see change in behaviour by subsituting 22 | the fifo with a normal file 23 | 24 | -------------------------------------------------------------------------------- /memory/README: -------------------------------------------------------------------------------- 1 | 2 | 3 | Investiage page virtual address and physical addresses 4 | ------------------------------------------------------ 5 | 6 | Use pmap `pidof command` to view the virtual address space of a running process 7 | You'll need to do a sudo if the command is not owned by the user 8 | 9 | frameit.c : Adapted from the internet (see file for credits) 10 | It takes and pid and a virtual address and tells us about the corresponding frame 11 | Used with sudo: like sudo ./frameit pid 400000 (address is assumed bas 16) 12 | (pid could also be self) 13 | You can create a fairly large program and see it doesnt have all the pages in the beginning! 14 | 15 | 16 | -------------------------------------------------------------------------------- /procs/forkloop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | 13 | /* Simple program that creates a copy process by using fork*/ 14 | void main(){ 15 | int child_pid; 16 | int x=0; 17 | int status; 18 | char spaces[]={0,0,0,0,0,0,0,0,0,0,0,0}; 19 | 20 | printf("PID=%d\n",getpid()); 21 | for (int i=0;i<3;i++){ 22 | int r = fork(); 23 | if (r == 0 ) // each child prints its info once! 24 | { 25 | spaces[x++]='.'; 26 | printf("%s PID=%d\n",spaces,getpid()); 27 | } 28 | } 29 | int i=rand()%5; 30 | sleep(i+5); 31 | } 32 | // printf("i=%d ; %d child of %d\n",i,getpid(),getppid()); 33 | -------------------------------------------------------------------------------- /files/pipecmd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void main(){ 7 | int p[2]; 8 | if ( pipe(p) < 0 ) { 9 | perror("pipe creation: "); 10 | exit(1); 11 | } 12 | int c=fork(); 13 | // alternately 14 | if ( c == 0 ) { 15 | dup2(p[1],1); // from now on in child 1 is same as p[1] 16 | close(p[0]); // dont need p[0] in child 17 | char string[]="This is the house that jack built"; 18 | printf("%s\n",string); 19 | } else if ( c > 0 ){ 20 | dup2(p[0],0); // from now on in parent 0 is same as p[0] 21 | close(p[1]); // dont need p[1] in parent 22 | char word[100]; 23 | while( scanf("%s",word) != EOF ) 24 | printf("GOT:%s\n",word); 25 | } else 26 | perror("Failed fork:"); 27 | } 28 | -------------------------------------------------------------------------------- /ipc/msgque/msg_reader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common.h" 7 | 8 | int main(){ 9 | // get the token for my queue 10 | key_t token = ftok (MYPROJECTPATH, MYPROJECTID); 11 | if ( token <= 0 ){ 12 | perror("Reader failed to get token"); 13 | exit(1); 14 | } 15 | printf("token = %d\n",token); 16 | // get or create the queue 17 | int qid = msgget (token, IPC_CREAT|0644); 18 | if (qid < 0 ){ 19 | perror("Reader failed to get queue"); 20 | exit(1); 21 | } 22 | struct msgbuf m1; 23 | int n = msgrcv(qid, &m1, MSGSIZE, 0, 0); 24 | if (n < 0 ){ 25 | perror("Reader failed to receive"); 26 | exit(1); 27 | } 28 | printf("%s",m1.mtext); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /procs/simple_exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #define COMMAND "/bin/ps" 13 | #define ARGS "/bin/ps", "-l" 14 | /* Simple program that executes (overlays) anoher program */ 15 | void main(){ 16 | 17 | // Execution of a general command with args 18 | char * overlaycmd = COMMAND ; 19 | char * params[] = { ARGS, NULL }; // looks like {"/bin/ps", "-l", NULL} 20 | 21 | printf("I am the executable....Before PID = %d\n",(int)getpid()); 22 | execv(overlaycmd,params); 23 | 24 | 25 | printf("After ... NEVER PRINT THIS if success..... PID = %d\n",(int)getpid()); 26 | perror("Failed execution:"); 27 | } 28 | -------------------------------------------------------------------------------- /docs/build/README: -------------------------------------------------------------------------------- 1 | PURPOSE: 2 | This directory is intended to illustrate usage of Makefile 3 | The aim is to do just enough to enable the student to start 4 | using 'make' to build executables on a regular basis 5 | 6 | MORE INFORMATION: 7 | See 'man make' for info on the make command 8 | See 9 | https://www.gnu.org/software/make/manual/html_node/Introduction.html#Introduction 10 | for more information on the Makefile format 11 | 12 | FILES: 13 | 14 | Makefile1 15 | contains a simple makefile for 16 | building the hello_world program 17 | 18 | Makefile2 extends Makefile2 and also builds printpid 19 | 20 | Makefile3 21 | Shows some additional tricks typically used to make 22 | Makefiles more generic .. often not needed at this level. 23 | 24 | -------------------------------------------------------------------------------- /misc/address.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int g=0; 6 | int const k=0; 7 | void main() { 8 | int x; 9 | int * a; 10 | int z[100]; 11 | a = (int *)malloc(10); 12 | printf("writecode) is at %p\n",write); 13 | printf("main(code) is at %p\n",main); 14 | printf("g (data) is at %p\n",&g); 15 | printf("a (heap) is %p\n",a); 16 | printf("x (stak) is at %p\n",&x); 17 | printf("a (stak) is at %p\n",&a); 18 | printf("z (stak) is at %p\n",&z); 19 | printf("k (gl kon) is at %p\n",&k); 20 | printf(" ......... you may want to use pmap to see the address space\n"); 21 | if ( mlock(a,10) < 0 ){ 22 | perror("main.mlock():"); 23 | exit(1); 24 | } 25 | sleep(10000); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /procs/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS= -g 3 | DEPS = 4 | OBJ = 5 | EXEC = loopy shell simple_exec simple_fork simple_getpid \ 6 | fork_and_termC fork_and_termP zomB reparent priority_ops \ 7 | syscallC exceptions fork_experiment \ 8 | sched_info sched_policychange sched_priochange 9 | OBJS = loopy.o shell.o simple_exec.o simple_fork.o simple_getpid.o \ 10 | fork_and_termC.o fork_and_termP.o zomB.o reparent.o priority_ops.o \ 11 | syscallC.o syscall.o exceptions.o fork_experiment.o \ 12 | sched_info.o sched_policychange.o sched_priochange.o 13 | 14 | all-execs: $(EXEC) assembly 15 | 16 | all: all-execs 17 | 18 | assembly: 19 | gcc -c syscall.s 20 | ld -o syscall syscall.o 21 | 22 | clean: 23 | rm -f $(OBJS) a.out $(EXEC) syscall 24 | 25 | help: 26 | echo all-execs/ all-objs /all /clean-all 27 | -------------------------------------------------------------------------------- /ipc/msgque/msg_writer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common.h" 8 | 9 | int main(){ 10 | // get the token for my queue 11 | key_t token = ftok (MYPROJECTPATH, MYPROJECTID); 12 | if ( token <= 0 ){ 13 | perror("Writer failed to get token"); 14 | exit(1); 15 | } 16 | printf("token = %d\n",token); 17 | // get or create the queue 18 | int qid = msgget (token, IPC_CREAT|0644); 19 | if (qid < 0 ){ 20 | perror("writer failed get queue:"); 21 | exit(1); 22 | } 23 | struct msgbuf m1; 24 | // fill in the send message text 25 | m1.mtype=TYPEA; 26 | strcpy(m1.mtext,"Hellow World\n"); 27 | int n = msgsnd(qid, &m1, MSGSIZE, 0); 28 | if (n < 0 ){ 29 | perror("sending failed:"); 30 | exit(1); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /ipc/shm-posix/README: -------------------------------------------------------------------------------- 1 | This contains a simple example to show how shared memory can be used 2 | between different processes. 3 | 4 | The example here uses POSIX shared memory interface. 5 | 6 | shm_ctl.c : Has individual operations open, close, unlink, 7 | It uses ftruncate and mmap to create the shared region 8 | in the address space. 9 | You can run two instances of this and see how they 10 | share space. Use mmap to investigate the mapping 11 | 12 | filler.c : Fills shared memory with some data 13 | 14 | reader.c : Reads and prints what is filled in the shared memory 15 | 16 | Usage: 17 | ./shm_ctl -h 18 | ./fl : to run the filler process (good to unlink at start) 19 | Note: The filler code zeros the shared area before 20 | it fills. So od -x /dev/shm/ex1 shows you the data 21 | in hex 22 | ./rd : to run the reader process 23 | -------------------------------------------------------------------------------- /ipc/named-pipes/fifo-reader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "common.h" 9 | 10 | int main(int argc, char * argv[]){ 11 | char pipename[20]=PIPENAME; 12 | if (argc >1) 13 | strcpy(pipename,argv[1]); 14 | int fd=open(pipename,O_RDONLY); 15 | if (fd < 0 ) { 16 | perror("open failed"); 17 | exit(1); 18 | } 19 | printf("Now reading and printing strings from the pipe:\n"); 20 | printf("Every read string is printed and * and newline appear at the end\n"); 21 | int MAXLEN=100; 22 | char string[MAXLEN]; 23 | while( 1 ) { 24 | int len = read(fd,string,MAXLEN); 25 | string[len]='*'; 26 | string[len+1]='\n'; 27 | if (len > 0 ) write(1,string,len+2); 28 | else // Now it is EOF 29 | break; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ipc/sockets/Makefile: -------------------------------------------------------------------------------- 1 | 2 | EXECS= tcp_c tcp_s tcp_concs tcp_long_cl \ 3 | udp_s udp_c udp_echo_s \ 4 | unx_s unx_c 5 | 6 | all: $(EXECS) 7 | 8 | tcp_c: tcp_client.c commons.h 9 | gcc -o tcp_c tcp_client.c 10 | 11 | tcp_long_cl: tcp_long_client.c commons.h 12 | gcc -o tcp_long_cl tcp_long_client.c 13 | 14 | tcp_s: tcp_server.c commons.h 15 | gcc -o tcp_s tcp_server.c 16 | 17 | tcp_concs: conc_server.c commons.h 18 | gcc -o tcp_concs conc_server.c 19 | 20 | 21 | udp_s: udp_server.c commons.h 22 | gcc -o udp_s udp_server.c 23 | 24 | udp_c: udp_client.c commons.h 25 | gcc -o udp_c udp_client.c 26 | 27 | udp_echo_s: udp_echo_server.c commons.h 28 | gcc -o udp_echo_s udp_echo_server.c 29 | 30 | unx_s: udp_server.c commons.h 31 | gcc -o unx_s udp_server.c 32 | 33 | unx_c: udp_client.c commons.h 34 | gcc -o unx_c udp_client.c 35 | 36 | clean: 37 | rm -f $(EXECS) 38 | -------------------------------------------------------------------------------- /utils/mymake: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CLEAN_FLAG="" 4 | 5 | # This function expects a list of directories 6 | make_in_dir() { 7 | if [ $# -eq 0 ]; then 8 | return 9 | fi 10 | for dir in $* ; do 11 | # for each item in the given list of arguments 12 | # If it is not a directory just skip, else 13 | if [ -d $dir ] ; then 14 | # go into the directory 15 | cd $dir 16 | # do a make in that directory if possible 17 | if [ -f Makefile ] ; then 18 | echo Making in $dir .... 19 | make $CLEAN_FLAG 20 | fi 21 | # recurse on the list of the directory 22 | make_in_dir * 23 | # pop back up 24 | cd .. 25 | fi 26 | done 27 | } 28 | 29 | if [ x"$1" == "xclean" ] ; then 30 | CLEAN_FLAG="clean" 31 | shift 32 | else 33 | CLEAN_FLAG="" 34 | fi 35 | 36 | echo Doing make $CLEAN_FLAG in $* 37 | 38 | make_in_dir $* 39 | 40 | 41 | -------------------------------------------------------------------------------- /procs/fork_and_termP.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | void main(){ 15 | int child_pid; 16 | int status; 17 | printf("1 PID = %d\n",(int)getpid()); // See this once only 18 | child_pid = fork(); // This is where all the aciton is 19 | printf("2 PID = %d, %d\n",(int)getpid(),child_pid); // See this twice 20 | if (child_pid == 0 ) { 21 | // child aims to terminate the parent process 22 | int parent_pid=getppid(); 23 | printf("Process ready to %d send a kill to Process %d \n", 24 | getpid(), parent_pid); 25 | getchar(); 26 | kill(parent_pid,SIGTERM); 27 | printf("Check that process %d exited\n", parent_pid); 28 | getchar(); 29 | } else { 30 | // parent loops indefinitely 31 | while (1) {} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ipc/shm/filler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common.h" 8 | void main(){ 9 | struct mystruct * s; 10 | // create the new shm 11 | // 12 | int id = shmget(SHM_KEY,sizeof(struct mystruct),IPC_CREAT|0644); 13 | if ( id < 0 ) { 14 | perror("Trying to create shm :"); 15 | exit(1); 16 | } 17 | // attach it to the current process 18 | // Note we decided we will use it as a certain structure 19 | s = shmat(id, (void * )NULL, 0); 20 | // 21 | s->count=0; 22 | srand(time(NULL)); 23 | int salt1=rand()%100; // salt1 should be a randome from 0..99 24 | int salt=salt1*100; // this is to get a seq of numbers ending 0..99 25 | for ( int i =0; i< salt1 ; i++){ 26 | // Now we write whatever we wish 27 | s->count ++; 28 | s->val[i]=salt+i; 29 | } 30 | // Now done, so detach 31 | shmdt(s); 32 | } 33 | -------------------------------------------------------------------------------- /ipc/simple-pipe/pipe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void main(){ 7 | int pfdA[2]; 8 | if ( pipe(pfdA) < 0 ) { 9 | perror("pipe creation: "); 10 | exit(1); 11 | } 12 | int c=fork(); 13 | // alternately 14 | if ( c == 0 ) { 15 | // Child is the writer 16 | char * string[]={"This ","is ","my ", "house ","."}; 17 | for (int i=0;i<5;i++) { 18 | write(pfdA[1],string[i],strlen(string[i])); 19 | // sleep(1); 20 | // for convenience I made child sleep 21 | } 22 | } else if ( c > 0 ){ 23 | // Parent is the reader // Is this important?? close(pfdA[1]); 24 | int MAXLEN=100; 25 | char string[MAXLEN]; 26 | while( 1 ) { 27 | printf("*\n"); 28 | int len = read(pfdA[0],string,MAXLEN); 29 | if (len > 0 ) write(1,string,len); 30 | else // Now it is EOF 31 | break; 32 | } 33 | } else 34 | perror("Failed fork:"); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /procs/simple_fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | /* Simple program that creates a copy process by using fork*/ 13 | void main(){ 14 | int child_pid; 15 | int status; 16 | printf("1 PID = %d\n",(int)getpid()); // See this once only 17 | child_pid = fork(); // This is where all the aciton is 18 | printf("2 PID = %d, %d\n",(int)getpid(),child_pid); // See this twice 19 | // Uncomment this for both processes to loop 20 | if (child_pid == 0 ) { 21 | printf("Child looping\n"); 22 | while (1) {} // short form for an infinite loop 23 | } else { 24 | // printf("Parent looping\n"); 25 | // while (1) {} 26 | // alternately 27 | printf("Parent waiting for child to finish\n"); 28 | wait(&status); 29 | printf("Child termineted.... so parent exiting \n"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /files/redirect.c: -------------------------------------------------------------------------------- 1 | #include "myincludes.h" 2 | #include 3 | #define CMP_ARGV(I,X) (strcmp(argv[I],X)==0) 4 | 5 | void print_help_exit(char * cmd){ 6 | printf("%s [-h|--help] redirect-outfile " 7 | "command-to-execute arg1 arg2 ...\n", 8 | cmd); 9 | exit(0); 10 | } 11 | int check_args(char * argv[]){ 12 | int i=0; 13 | for(i=1;argv[i]!=NULL;i++) { 14 | if (CMP_ARGV(i,"-h") || CMP_ARGV(i,"--help")) { 15 | print_help_exit(argv[0]); 16 | } 17 | } 18 | return i; 19 | } 20 | 21 | void main(int argc, char * argv[]){ 22 | int n = check_args(argv); 23 | if (n < 3 ) 24 | print_help_exit(argv[0]); 25 | char * of=argv[1]; 26 | char * cmd=argv[2]; 27 | char ** newlist=&argv[2]; 28 | // This is to setup redirection 29 | int ofd = open(of,O_WRONLY|O_CREAT,S_IWUSR|S_IRUSR); 30 | if (ofd < 0 ) { 31 | printf("** Open %s failed",of); 32 | exit(1); 33 | } else { 34 | dup2(ofd,1); 35 | } 36 | 37 | execvp(cmd,newlist); 38 | } 39 | -------------------------------------------------------------------------------- /procs/fork_and_termC.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | void main(){ 15 | int child_pid; 16 | int status; 17 | printf("1 PID = %d\n",(int)getpid()); // See this once only 18 | child_pid = fork(); // This is where all the aciton is 19 | printf("2 PID = %d, %d\n",(int)getpid(),child_pid); // See this twice 20 | if (child_pid == 0 ) { 21 | printf("Child looping\n"); 22 | while (1) {} // short form for an infinite loop 23 | } else { 24 | // printf("Parent looping\n"); 25 | // while (1) {} 26 | // alternately 27 | printf("Process ready to %d send a kill to Process %d \n", 28 | getpid(), child_pid); 29 | getchar(); 30 | kill(child_pid,SIGTERM); 31 | printf("Check that process %d exited\n", child_pid); 32 | getchar(); 33 | wait(&status); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /files/readfile.c: -------------------------------------------------------------------------------- 1 | // open the file twice 2 | #include "myincludes.h" 3 | #include 4 | #define CMP_ARGV(I,X) (strcmp(argv[I],X)==0) 5 | void main(int argc, char * argv[]){ 6 | char buf[100]; 7 | char fname[50]="xyz"; 8 | 9 | if (argc > 1) 10 | strcpy(fname,argv[1]); 11 | 12 | int fd1 = open(fname,O_RDONLY); 13 | printf("fd1 is %d\n",fd1); // expect to see 3 14 | 15 | int n = read(fd1,buf,10); 16 | write(1,buf,10); // use write(2) to print to the screen 17 | 18 | close(fd1); 19 | 20 | // The below part shows how file descriptors get allocated: 21 | // Uncomment to see it work 22 | /* 23 | 24 | // close the STDIN 25 | close(0); 26 | // open the same file 27 | fd1 = open(fname,O_RDONLY); 28 | printf("\nfd1 is %d\n",fd1); 29 | 30 | // now try to read from this file 31 | n = read(fd1,buf,10); 32 | write(1,buf,10); 33 | 34 | // Lets try scanf 35 | scanf("%s",buf); 36 | printf("\n%s\n",buf); 37 | 38 | // What is your conclusion ? 39 | */ 40 | 41 | } 42 | -------------------------------------------------------------------------------- /docs/build/Makefile2: -------------------------------------------------------------------------------- 1 | # A slightly enhanced.. 2 | # SIMPLE FIRST VERSION OF THE Makefile with some useful 3 | # additions 4 | # 5 | # The next few lines are just shorthand definitions, 6 | # 7 | # We want to make two executables 8 | EXEC=hello_world printpid 9 | CC=gcc 10 | 11 | # ------------- the target and how to make ------------ 12 | 13 | # The first is always the default target to build 14 | # lets use this to list all the executables to build 15 | 16 | #Target 1 17 | all: $(EXEC) 18 | 19 | # executables : one by one say how to make each executable 20 | # note that hello_world executable depends on both the 21 | # hello_world.c and the hello_world.h so we list both files 22 | # as dependencies. 23 | # Target 2 24 | hello_world: hello_world.c hello_world.h 25 | $(CC) -o hello_world hello_world.c 26 | 27 | # Target 3 28 | printpid: printpid.c 29 | $(CC) -o printpid printpid.c 30 | 31 | 32 | # Target 4 33 | # cleanup utility - quite useful shorthand 34 | clean: 35 | rm -f $(EXEC) 36 | -------------------------------------------------------------------------------- /docs/build/Makefile1: -------------------------------------------------------------------------------- 1 | # A SIMPLE FIRST VERSION OF THE Makefile for one executable 2 | 3 | 4 | # ------------- the target and how to make ------------ 5 | 6 | # Lines come in groups of this form: 7 | # : 8 | # 9 | # 10 | # Wierd: Did you notice the mentioned above???? 11 | 12 | # In our case: 13 | # "hello_world" executable depends on 14 | # both "hello_world.c" and "hello_world.h" files 15 | # "hello_world" is built using gcc 16 | # Target 1 17 | hello_world: hello_world.c hello_world.h 18 | gcc -o hello_world hello_world.c 19 | 20 | # Did you find the in the above example? 21 | 22 | # -------------- Here is a useful target ------------- 23 | # cleanup utility - quite useful shorthand 24 | # Target 2 25 | clean: 26 | rm -f hello_world 27 | 28 | # note in the case of target "clean" it has no dependencies which means that it will check nothing and do the command :-) 29 | # 30 | # Target 3 31 | run: 32 | ./hello_world 33 | -------------------------------------------------------------------------------- /ipc/named-pipes/fifo-writer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common.h" 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char * argv[]){ 13 | int j=0; 14 | char pipename[20]=PIPENAME; 15 | if (argc >1) 16 | strcpy(pipename,argv[1]); 17 | 18 | int fd = open(pipename,O_WRONLY); 19 | if ( fd < 0 ) { 20 | perror("Open failed"); 21 | exit(1); 22 | } 23 | char n[2]=" "; // this will hold one char '0'..'9' 24 | char * string[]={n," This ","is ","server ", "sentence","."}; 25 | while(1) { 26 | string[0][0]='0'+j; // each string starts with a sequence digit 27 | for (int i=0;i<5;i++) { 28 | if( write(fd,string[i],strlen(string[i]))< 0){ 29 | perror("writer write():"); 30 | exit(1); 31 | } 32 | // sleep(1); 33 | } 34 | printf("sent %d\n",j); 35 | j=(j+1)%10; 36 | sleep(2); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ipc/shm/reader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "common.h" 6 | 7 | void main(){ 8 | struct shmid_ds sbuf; 9 | struct mystruct * s; 10 | // create the new shm if it doesnt exist 11 | // 12 | int id = shmget(SHM_KEY,sizeof(struct mystruct),IPC_CREAT|0644); 13 | if ( id < 0 ) { 14 | perror("Trying to create shm:"); 15 | exit(1); 16 | } 17 | // attach it to the current process 18 | // Note we decided we will use it as a certain structure 19 | s = shmat(id, (void * ) NULL, 0); 20 | // 21 | for (int i=0;i < s->count;i++) { 22 | // Now we will read as much as we can whatever we wish 23 | printf("%d\n",s->val[i]); 24 | } 25 | // Now done, so detach 26 | /* 27 | shmctl(id,IPC_RMID,&sbuf); 28 | shmctl(id,IPC_STAT,&sbuf); 29 | printf("size =%ld\n",sbuf.shm_segsz); 30 | printf("cpid =%d\n",sbuf.shm_cpid); 31 | printf("lpid =%d\n",sbuf.shm_lpid); 32 | printf("nattch =%ld\n",sbuf.shm_nattch); 33 | */ 34 | shmdt(s); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ipc/shm-posix/reader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "common.h" 10 | void main(){ 11 | struct mystruct * s; 12 | // create the new shm 13 | // 14 | int fd = shm_open(SHM_NAME, O_RDWR | O_CREAT,0644); 15 | if ( fd < 0 ) { 16 | perror("Trying to create shm :"); 17 | exit(1); 18 | } 19 | // set size 20 | // ftruncate(fd, sizeof(struct mystruct)); 21 | // Note we decided we will use it as a certain structure 22 | s = mmap(NULL, sizeof(struct mystruct), PROT_READ, 23 | MAP_SHARED, fd, 0); 24 | if (s == NULL) { 25 | perror("couldn't map new"); 26 | exit(1); 27 | } else { 28 | printf("Mapped shm to address space; "); 29 | } 30 | printf("Reading %d numbers:\n",s->count); 31 | for (int i=0;i < s->count;i++) { 32 | // Now we will read as much as we can whatever we wish 33 | printf("%d\n",s->val[i]); 34 | } 35 | 36 | // Now done, so close 37 | close(fd); 38 | } 39 | -------------------------------------------------------------------------------- /pthreads/simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SLEEPTIME 100 9 | 10 | int gettid(); 11 | 12 | char global[20]="Hello How are you?"; 13 | 14 | void * thread_function(void * tid){ 15 | printf("T=%d , P=%d sleeping...\n", gettid(), getpid()); 16 | // pthread_exit(NULL); 17 | sleep(SLEEPTIME); 18 | printf("... %d woke up\n", gettid()); 19 | // to demonstrate they share the same address space 20 | strcpy(global,"bye bye"); 21 | printf("Child Wrote:%s\n",global); 22 | return NULL ; 23 | } 24 | 25 | int main(int argc, char * argv[]){ 26 | pthread_t tid; // This is not an integer. non portable structure type 27 | 28 | printf("Starting with T=%d P=%d\n",gettid(), getpid()); 29 | 30 | int r = pthread_create(&tid,NULL,thread_function,(void *)tid); 31 | 32 | // pthread_cancel(tid); 33 | sleep(SLEEPTIME); 34 | // Try this for fun for(;;) ; 35 | pthread_join(tid,NULL); 36 | printf("Parent Sees:%s\n",global); 37 | exit(0); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /misc/check-endian.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // create a number with the characters 'A'(0x41), 'B', 'C', 'D' 5 | unsigned int n=0x41424344; 6 | char least_significant_char=(char)0x44; 7 | 8 | // If Least Significant appears first, it is little endian 9 | // If Most significant appears first, it is big endian 10 | // 11 | int main(int argc, char * argv[]){ 12 | printf("Originally least_significant is %c, here are the extracted characters:\n",least_significant_char); 13 | printf(" %d ", (int)sizeof(unsigned int)); 14 | char f,c; 15 | f = c = * (char *) &n ; putchar( c ); putchar(' '); 16 | c = * ((char *) &n + 1); putchar( c ); putchar(' '); 17 | c = * ((char *) &n + 2); putchar( c ); putchar(' '); 18 | c = * ((char *) &n + 3); putchar( c ); putchar('\n'); 19 | 20 | if (argc > 1 && strcmp(argv[1],"-s")==0){ 21 | if (f == least_significant_char ) 22 | printf("Least significant appears first, so it is little endian\n"); 23 | else 24 | printf("Most significant appears first, so it is big-endian\n"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /files/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | Some miscellaneous files to try things out 3 | 4 | FILES 5 | check-fileinfo.c calls stat to get info about a file 6 | ./check-fileinfo 7 | flush.c using fflush, the notion of buffer and flushing 8 | repeated_printf.c understanding how C library is using buffering 9 | file_as_a_lock.c Using file locking 10 | readfile.c Use open() read() and write() syscalls 11 | also tells us a bit more about file descriptors 12 | test_link.c A Simple program to test hard and soft links 13 | : do test_link --help for more info 14 | test2_link.c A Simple program to test hard and soft links : 15 | : introduced unlink.... must cleanup 16 | flocking.c A simple program to show how locking works 17 | To see it work, run two instances of the program on different windows and see ps -alx 18 | redirect.c Example using open and dup for redirection 19 | pipecmd.c Use pipe between parent and child using 20 | usingdup.c A program to show the effect of using dup 21 | instead of open the file twice 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/simple-pipe-linux-commandline: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # simple code to show how piping works and a feel for the way people use it 3 | 4 | # This uses sed to change the first occurrence of void to int 5 | cat x.c | sed s/void/int/ 6 | # More examples on sed, see https://linuxhint.com/50_sed_command_examples/ 7 | # And also https://edoras.sdsu.edu/doc/sed-oneliners.html 8 | 9 | 10 | # This uses awk to do somehing like cat -n x.c 11 | cat x.c | awk ' { print NR " : " $0 }' 12 | # Handy awk one-liners https://linoxide.com/useful-awk-one-liners-to-keep-handy/ 13 | 14 | # This uses perl to add a line before and after the contents of x.c 15 | cat x.c | perl -pE 'BEGIN{say "// Sample header"} END{say "// Sample tail"}' 16 | # Handy perl stuff https://learnbyexample.github.io/learn_perl_oneliners/one-liner-introduction.html 17 | 18 | # The next one is NOT a command line pipe, but I find it very useful 19 | # This copies x.txt to x.txt.back (-i can be used without .bak as well) 20 | # Then is replaces all occurrences of SMALL by BIG in x.txt 21 | # The useful thing is it changes x.txt itself, not sending stuff to stdout. 22 | perl -pi.bak -e s/SMALL/BIG/g x.txt 23 | 24 | -------------------------------------------------------------------------------- /files/usingdup.c: -------------------------------------------------------------------------------- 1 | // open the file twice 2 | #include "myincludes.h" 3 | #include 4 | #define CMP_ARGV(I,X) (strcmp(argv[I],X)==0) 5 | void withoutdup(){ 6 | char buf[100]; 7 | 8 | // open same file twice 9 | int fd1 = open("xyz",O_RDONLY); 10 | int fd2 = open("xyz",O_RDONLY); 11 | 12 | // read from first fd and print on screen 13 | int n = read(fd1,buf,10); 14 | write(1,buf,10); 15 | 16 | // read from second fd and print on screen 17 | n = read(fd2,buf,10); 18 | write(1,buf,10); 19 | 20 | // they have two different internal structures/information 21 | } 22 | void withdup(){ 23 | char buf[100]; 24 | 25 | // open the file only once 26 | int fd1 = open("xyz",O_RDONLY); 27 | // duplicate the fd ... (NOT open again) 28 | int fd2 = dup(fd1); 29 | 30 | // read using fd1 and print on the screen 31 | int n = read(fd1,buf,10); 32 | write(1,buf,10); 33 | 34 | // read using fd2 and print on the screen 35 | n = read(fd2,buf,10); 36 | write(1,buf,10); 37 | 38 | // the two fds share the same internal structures 39 | } 40 | void main(int argc, char *argv[]){ 41 | if (argc > 1 ) { 42 | if (CMP_ARGV(1,"--nodup") || CMP_ARGV(1,"-n")) 43 | withoutdup(); 44 | } else 45 | withdup(); 46 | } 47 | -------------------------------------------------------------------------------- /files/test_link.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | // #define DEBUG 1 10 | 11 | // Small macro to test if argv[1] is X 12 | #define COMMAND(X) (strcmp(argv[1],X)==0) 13 | // future:: COMMAND(i,X) (strcmp(argv[i],X)==0) 14 | 15 | int main(int argc, char ** argv){ 16 | 17 | 18 | // Process arguments - here just printing for fun 19 | #ifdef DEBUG 20 | printf("%d\n", argc); 21 | for( int i = 0; i 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | int new_priority=10; 9 | 10 | void show_and_get(char *msg){ 11 | printf(msg); 12 | printf("\n Press enter to continue ..."); 13 | getchar(); 14 | } 15 | 16 | void main(){ 17 | // What scheduler policy is my system using for me? 18 | int mypid=getpid(); 19 | int sdlr = sched_getscheduler(mypid); 20 | printf("My scheduler is: "); 21 | switch (sdlr){ 22 | // Normal policies 23 | case SCHED_OTHER: 24 | printf("SCHED_OTHER\n"); 25 | break; 26 | default: 27 | printf("Unexpected policy %d\n",sdlr); 28 | } 29 | // What scheduler policy parameter (in particular the priority 30 | struct sched_param param; 31 | sched_getparam(mypid,¶m); 32 | 33 | // change my process priority ie nice value since it is SCHED_OTHER 34 | printf("setting my priority to : %d\n",new_priority); 35 | setpriority(PRIO_PROCESS,mypid,new_priority); 36 | // we can also change priotity in one short for 37 | // all process for a user. 38 | // setpriority(PRIO_USER,getuid(),new_priority); 39 | 40 | printf("Now my process priority is : %d\n",getpriority(PRIO_PROCESS,0)); 41 | show_and_get(""); 42 | } 43 | -------------------------------------------------------------------------------- /ipc/shm-posix/filler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "common.h" 11 | void main(){ 12 | struct mystruct * s; 13 | // create the new shm 14 | // 15 | int fd = shm_open(SHM_NAME,O_RDWR | O_CREAT,0644); 16 | if ( fd < 0 ) { 17 | perror("Trying to create shm :"); 18 | exit(1); 19 | } 20 | // set size 21 | ftruncate(fd, sizeof(struct mystruct)); 22 | // Note we decided we will use it as a certain structure 23 | s = mmap(NULL, sizeof(struct mystruct), PROT_READ | PROT_WRITE, 24 | MAP_SHARED, fd, 0); 25 | if (s == NULL) { 26 | perror("couldn't map new"); 27 | exit(1); 28 | } else { 29 | printf("Mapped shm to address space; "); 30 | } 31 | memset(s, 0, sizeof(struct mystruct)); 32 | s->count=0; 33 | srand(time(NULL)); 34 | int nums=rand()%100; // nums should be a randome from 0..99, say 85 35 | int start=nums*100; // the seq is 8500 8501 ... 8504 36 | for ( int i =0; i< nums ; i++){ 37 | // Now we write whatever we wish 38 | s->count ++; 39 | s->val[i]=start+i; 40 | } 41 | printf("First num: %d ; last num: %d\n",start,start+(nums-1)); 42 | // Now done, so close 43 | close(fd); 44 | } 45 | -------------------------------------------------------------------------------- /ipc/sockets/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | learning about sockets 3 | 4 | FILES 5 | common.h : Defines the server port number 6 | 7 | Use these in groups: 8 | 9 | 0. A simple client and server using a utility called netcat (or nc) 10 | simple_tcp_server.sh : This is the server, will listen for connections 11 | simple_tcp_client.sh : This is the client, will make connections 12 | 13 | 1. TCP Single send receive pair 14 | tcp_client.c : A simple TCP client. Sends only one message. 15 | tcp_server.c : A simple TCP server. Receives one message only 16 | from a client. 17 | 18 | 2. TCP Send receive until client closes - a pair 19 | conc_server.c : A concurrent server. Will send/rcv messages as long 20 | as the client does not close the connection. 21 | tcp_long_client.c : A TCP client that send multiple messages. 22 | This is intended to be used with conc_server.c 23 | 24 | 3. UDP 25 | udp_server.c : A simple UDP server 26 | udp_echo_server.c : A UDP server that repeatedly 27 | receives from any clients 28 | udp_client.c : A simple UDP client 29 | Can pair this client with one of the above servers 30 | NOTE: One could also use nc -u 127.0.0.1 9999 as a client 31 | 32 | 33 | 4. UNIX 34 | unx_server.c : A simple UNIX SOCK server. 35 | unx_client.c : A simple UNIX SOCK client. 36 | -------------------------------------------------------------------------------- /ipc/sockets/tcp_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "commons.h" 10 | 11 | int main(int argc, char * argv[]){ 12 | // declare socket vars 13 | int fsock; 14 | struct sockaddr_in server; 15 | char str[100]; 16 | char suffix[50]="Client Message from "; 17 | sprintf(str,"%s %u\n",suffix, getpid()); 18 | 19 | fillzero(server); 20 | 21 | fsock=socket(AF_INET, SOCK_STREAM , 0); 22 | if (fsock < 0 ){ 23 | perror("socket():"); 24 | exit(1); 25 | } 26 | 27 | server.sin_family = AF_INET; 28 | server.sin_port = htons(SRV_PORT); 29 | server.sin_addr.s_addr = inet_addr("127.0.0.1"); 30 | 31 | // connect to the server on the sock 32 | int r = connect(fsock,(struct sockaddr *) &server, sizeof(server)); 33 | if (r < 0 ){ 34 | perror("connect():"); 35 | exit(1); 36 | } 37 | 38 | // send 39 | r = send(fsock,str,strlen(str),0); 40 | if (r < 0 ){ 41 | perror("send():"); 42 | exit(1); 43 | } 44 | 45 | // receive 46 | r = recv(fsock,str,100,0); 47 | if (r < 0 ){ 48 | perror("recv():"); 49 | exit(1); 50 | } 51 | str[r]='\0'; 52 | printf("Got: %s\n",str); 53 | 54 | // exit 55 | exit(0); // automatically socket is closed from client end 56 | } 57 | -------------------------------------------------------------------------------- /misc/timer_intr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int g=0; 7 | 8 | void handler(int signo) { 9 | struct timeval tv; 10 | struct timezone tz; 11 | 12 | 13 | if (signo == SIGALRM) 14 | printf("received SIGALRM when g is %d\n",g); 15 | gettimeofday(&tv,&tz); 16 | printf("time is --> %ld\n",tv.tv_sec); 17 | g++; 18 | } 19 | 20 | void set_my_signal(){ 21 | if (signal(SIGALRM, handler) == SIG_ERR) { 22 | perror("setting signal failed"); 23 | exit(1); 24 | } 25 | } 26 | 27 | 28 | int main () { 29 | struct itimerval timer; 30 | struct itimerval timer2; 31 | 32 | // set handler 33 | set_my_signal(); 34 | 35 | // set the initial timeout values 36 | timer.it_value.tv_sec = 10; // first expires after 10 sec 37 | timer.it_value.tv_usec = 0; // Recall: 1,000,000 us is one second. 38 | // and after that timeout values 39 | timer.it_interval.tv_sec = 5; // expires every 5 sec thereafter 40 | timer.it_interval.tv_usec = 0; 41 | 42 | // print the time now. 43 | struct timeval tv; 44 | struct timezone tz; 45 | gettimeofday(&tv,&tz); 46 | printf("time is --> %ld\n",tv.tv_sec); 47 | 48 | // start the timer 49 | setitimer (ITIMER_REAL, &timer, NULL); 50 | 51 | while (1); 52 | 53 | 54 | /* Do busy work. */ 55 | } 56 | -------------------------------------------------------------------------------- /pthreads/Makefile: -------------------------------------------------------------------------------- 1 | EXECS= simple pc \ 2 | find_some_primes find_some_primes_2r \ 3 | find_some_primes_mutex find_some_primes_cv \ 4 | find_some_primes_cv_many \ 5 | update_balance update_balance_mutex 6 | 7 | all: $(EXECS) 8 | 9 | # gettid() is linux specific and gives linux LWP ID to the thread 10 | # compiling gives a warning, that I neglect 11 | simple: simple.c 12 | gcc -o simple -pthread simple.c 13 | 14 | update_balance: update_balance.c 15 | gcc -o update_balance -pthread update_balance.c 16 | 17 | update_balance_mutex: update_balance_mutex.c 18 | gcc -o update_balance_mutex -pthread update_balance_mutex.c 19 | 20 | find_some_primes: find_some_primes.c 21 | gcc -o find_some_primes -pthread find_some_primes.c -lm 22 | 23 | find_some_primes_2r: find_some_primes_2r.c 24 | gcc -o find_some_primes_2r -pthread find_some_primes_2r.c -lm 25 | 26 | find_some_primes_mutex: find_some_primes_mutex.c 27 | gcc -o find_some_primes_mutex -pthread find_some_primes_mutex.c -lm 28 | 29 | find_some_primes_cv: find_some_primes_cv.c 30 | gcc -o find_some_primes_cv -pthread find_some_primes_cv.c -lm 31 | 32 | find_some_primes_cv_many: find_some_primes_cv_many.c 33 | gcc -o find_some_primes_cv_many -pthread find_some_primes_cv_many.c -lm 34 | 35 | pc: prod_con.c safe_ops.c safe_ops.h 36 | gcc -o pc -pthread safe_ops.c prod_con.c 37 | 38 | clean: 39 | rm -f $(EXECS) a.out 40 | -------------------------------------------------------------------------------- /docs/README-submission-guidelines: -------------------------------------------------------------------------------- 1 | PURPOSE: 2 | Provide suidelines to enable students to submit assignments in a uniform way to simplify build and execution: 3 | 4 | 0. Write a first version of your program and a first version of the Makefile 5 | Create the Makefile from the template located in: 6 | docs/build/Makefile? 7 | 8 | 1. Use your makefile while doing your development. (Not as an afterthought!) 9 | Often it is good to simply do "make" just to be sure you are 10 | not breaking anything. See the compilation steps in the output to be sure. 11 | 12 | 2. Once you have done development, testing etc. Then tar things together. 13 | tar cvf 14 | tar cvf IMT2019789-Assn1.tar Makefile hello_world.c hello_world.h 15 | This combines into the new file IMT2019789-Add1.tar 16 | all the files listed after, i.e. Makefile hello_world.c and hello_world.h 17 | 18 | 3. Test your tar file in a new empty directory: As an example: 19 | mkdir /tmp/testdir 20 | cp IMT2019789-Assn1.tar /tmp/testdir 21 | cd /tmp/testdir 22 | tar xvf IMT2019789-Assn1.tar # Note the "x" in "xvf" it is for extraction 23 | make 24 | 25 | It should build properly, and execute properly after that. 26 | 27 | 4. Submit the tar file AFTER you are happy your build and execution worked 28 | FROM THE TEST DIRECTORY. 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /procs/syscall.s: -------------------------------------------------------------------------------- 1 | ######################### 2 | # taken from: https://cs.lmu.edu/~ray/notes/gasexamples/ 3 | # See the above site for more on x86-64 assembly 4 | # On my system the syscall numbers are listed in this file: 5 | # /usr/include/x86_64-linux-gnu/asm/unistd_64.h 6 | # Note: This is pure assembly and uses no C libraries 7 | # We dont want gcc to invoke ld in the usual way, so compile differently. 8 | # To compile: 9 | # $ gcc -c syscall.s 10 | # $ ld syscall.o 11 | # Then execute: 12 | # $ ./a.out 13 | ######################## 14 | .global _start 15 | 16 | .text 17 | _start: 18 | # write(1, message, length of message) # see man page WRITE(2) 19 | mov $1, %rax # system call 1 is write 20 | mov $1, %rdi # file handle 1 is stdout 21 | mov $message, %rsi # address of string to output 22 | mov $len, %rdx # number of bytes 23 | syscall # invoke operating system to do the write 24 | 25 | # exit(0) # see man page EXIT(2) 26 | mov $60, %rax # system call 60 is exit 27 | xor %rdi, %rdi # we want return code 0 28 | syscall # invoke operating system to exit 29 | message: 30 | .ascii "Hello, from assembly world\n" 31 | len = . - message 32 | 33 | -------------------------------------------------------------------------------- /files/repeated_printf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define NOFLUSH "noflush" 7 | #define FFLUSH "fflush" 8 | #define SCANF "scanf" 9 | #define GETCHAR "getchar" 10 | 11 | // set FLUSH to be one of the four above 12 | #define FLUSH NOFLUSH 13 | 14 | #define CMP(X,Y) strcmp(X,Y)==0 15 | 16 | // C Langauge buffering.. more experimentation 17 | // It appears the buffered read(scanf getchar etc) sometimes 18 | // causes stdout to be flushed. 19 | 20 | void main(){ 21 | int j; 22 | for(int i=0;i<10;i++) { 23 | // do strace and see what system calls are executed 24 | // does write happen repeatedly? 25 | printf(" %d ,",i); 26 | // Without any of the below flushing ways 0, 1, 2, 3,... 27 | // get printed at the end (see the sleep below) 28 | // different ways to flush: 29 | if ( CMP(FLUSH,FFLUSH) ) { 30 | // This one is the standard way 31 | // Call fflush for event time i%4==0 32 | if (i%4==0) 33 | fflush(stdout); 34 | } else if (CMP(FLUSH,SCANF) ) { 35 | // It so happens that doing a scanf when the 36 | // input buffer is empty also casuses an flushing 37 | // .. give multiple integers here for fun 38 | // .. also for fun give a non integer as input 39 | if (scanf("%d",&j)==EOF) 40 | exit(0); 41 | } else if ( CMP(FLUSH,GETCHAR) ) { 42 | // A getchar too: try multiple characters here for fun 43 | getchar(); 44 | } 45 | sleep(1); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ipc/named-pipes/fifo-re-wr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common.h" 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char * argv[]){ 13 | 14 | 15 | printf("Demonstrate both read and write from a single process.\n"); 16 | printf("Works, but hangs waiting in the end. Can you explain why?\n"); 17 | int j=0; 18 | char pipename[20]=PIPENAME; 19 | if (argc >1) 20 | strcpy(pipename,argv[1]); 21 | 22 | int fd = open(pipename,O_RDWR); 23 | if ( fd < 0 ) { 24 | perror("Open failed"); 25 | exit(1); 26 | } 27 | char n[2]=" "; // this will hold one char '0'..'9' 28 | char * string[]={n," This ","is ","server ", "sentence","."}; 29 | for(int i=0;i<5;i++) { 30 | string[0][0]='0'+j; // each string starts with a sequence digit 31 | for (int i=0;i<5;i++) { 32 | if( write(fd,string[i],strlen(string[i]))< 0){ 33 | perror("writer write():"); 34 | exit(1); 35 | } 36 | // sleep(1); 37 | } 38 | printf("sent %d\n",j); 39 | j=(j+1)%10; 40 | sleep(2); 41 | } 42 | for(int i=0;i<5;i++){ 43 | } 44 | int MAXLEN=100; 45 | char rstring[MAXLEN]; 46 | for(int i=0;i<5;i++) { 47 | int len = read(fd,rstring,MAXLEN); 48 | rstring[len]='*'; 49 | rstring[len+1]='\n'; 50 | if (len > 0 ) write(1,rstring,len+2); 51 | else // Now it is EOF 52 | break; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ipc/sockets/unx_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "commons.h" 12 | 13 | int main(int argc, char * argv[]){ 14 | // declare socket vars 15 | int fsock; 16 | struct sockaddr_un server; 17 | char str[100]; 18 | char suffix[100]="Client Message from "; 19 | sprintf(str,"%s %u\n",suffix, getpid()); 20 | 21 | fillzero(server); 22 | 23 | fsock=socket(AF_UNIX, SOCK_STREAM , 0); 24 | if (fsock < 0 ){ 25 | perror("socket():"); 26 | exit(1); 27 | } 28 | 29 | server.sun_family = AF_UNIX; 30 | strcpy( server.sun_path, UNIX_SOCK_PATH ); 31 | 32 | // connect to the server on the sock 33 | printf("Connecting....\n"); 34 | int r = connect(fsock,(struct sockaddr *) &server, sizeof(server)); 35 | if (r < 0 ){ 36 | perror("connect():"); 37 | exit(1); 38 | } 39 | printf("....Connected\n"); 40 | 41 | // send 42 | printf("Sending....\n"); 43 | r = send(fsock,str,strlen(str),0); 44 | if (r < 0 ){ 45 | perror("send():"); 46 | exit(1); 47 | } 48 | printf("....Sent\n"); 49 | 50 | // receive 51 | printf("Receiving....\n"); 52 | r = recv(fsock,str,100,0); 53 | if (r < 0 ){ 54 | perror("recv():"); 55 | exit(1); 56 | } 57 | printf("....Received\n"); 58 | str[r]='\0'; 59 | printf("Got: %s\n",str); 60 | 61 | // exit 62 | exit(0); // automatically socket is closed from client end 63 | } 64 | -------------------------------------------------------------------------------- /misc/mmap1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | void handler(int signo) { 12 | if (signo == SIGUSR1) 13 | printf("received SIGUSR1\n"); 14 | } 15 | 16 | void set_my_signal(){ 17 | if (signal(SIGUSR1, handler) == SIG_ERR) { 18 | perror("setting signal failed"); 19 | exit(1); 20 | } 21 | } 22 | 23 | int g; 24 | 25 | int main(){ 26 | set_my_signal(); 27 | printf("A sinal handler is setup, now pausing\n"); 28 | pause(); 29 | char * new_region = mmap(NULL, 4096, 30 | /* readable and writable */ PROT_READ|PROT_WRITE, 31 | /* shared among procs, not file mapped */ MAP_SHARED |MAP_ANONYMOUS, 32 | /* no fd and offset */ -1, 0); 33 | if (new_region == MAP_FAILED ) { 34 | perror("mmap for new_region"); 35 | exit(1); 36 | } 37 | int status; 38 | strcpy(new_region,"Joker\n"); 39 | printf("Before fork: wrote Joker into new_region\n"); 40 | if(fork()==0){ 41 | // Child write hello world into the new_region 42 | printf("In child..will pause\n"); 43 | pause(); 44 | printf("In child..will write child hello message and exit\n"); 45 | strcpy(new_region, "hello from child!\n"); 46 | exit(0); 47 | } 48 | printf("In parent..will wait for child to exit\n"); 49 | wait (&status); 50 | // Parent reads the new_region 51 | printf("Parent.. woke-up and found this message-%s\n",new_region); 52 | } 53 | -------------------------------------------------------------------------------- /ipc/sockets/tcp_long_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "commons.h" 10 | 11 | int main(int argc, char * argv[]){ 12 | // declare socket vars 13 | int fsock; 14 | struct sockaddr_in server; 15 | char str[200]; 16 | char suffix[50]="Client Message from "; 17 | sprintf(str,"%s %u\n",suffix, getpid()); 18 | 19 | 20 | fsock=socket(AF_INET, SOCK_STREAM , 0); 21 | if (fsock < 0 ){ 22 | perror("socket():"); 23 | exit(1); 24 | } 25 | 26 | fillzero(server); 27 | server.sin_family = AF_INET; 28 | server.sin_port = htons(SRV_PORT); 29 | server.sin_addr.s_addr = inet_addr("127.0.0.1"); 30 | 31 | // connect to the server on the sock 32 | int r = connect(fsock,(struct sockaddr *) &server, sizeof(server)); 33 | if (r < 0 ){ 34 | perror("connect():"); 35 | exit(1); 36 | } 37 | 38 | // send a receive 5 messages on this connection 39 | int i=0; 40 | while(i < 5 ) { 41 | // send 42 | sprintf(str,"%s %u %d\n",suffix, getpid(),i); 43 | r = send(fsock,str,strlen(str),0); 44 | if (r < 0 ){ 45 | perror("send():"); 46 | exit(1); 47 | } 48 | 49 | // receive 50 | r = recv(fsock,str,100,0); 51 | if (r < 0 ){ 52 | perror("recv():"); 53 | exit(1); 54 | } 55 | str[r]='\0'; 56 | printf("Client recvd: %s\n",str); 57 | i++; 58 | sleep(5); 59 | } 60 | 61 | // exit 62 | exit(0); // automatically socket is closed from client end 63 | } 64 | -------------------------------------------------------------------------------- /procs/loopy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | //Possible values for option 8 | #define BUSY 1 9 | #define SLEEPY 2 10 | #define KERNEL 3 11 | //run this on one terminal with different options 12 | //on another terminal run top, see where this program is in the list 13 | //check the amount of time consumed by the PROCESS (%cpu) 14 | //check also the amount of time the SYSTEM is in user space(us) vs kernel space(sy) 15 | void main(int argc, char ** argv){ 16 | int option=SLEEPY; 17 | // Find and print the option 18 | if (argc <= 1 ) 19 | printf("*Too few arguments: %s [sleepy|busy|kernel] \n",argv[0]), 20 | exit(1); 21 | if (strcmp(argv[1],"busy") == 0 ) 22 | option=BUSY; 23 | else if (strcmp(argv[1],"kernel") == 0) 24 | option=KERNEL; 25 | 26 | printf("%s = %d\n", argv[1], (int)getpid()); 27 | 28 | int i=0; 29 | while (1) { // An infinite loop 30 | if (option==SLEEPY) { 31 | // a "sleepy" process will be in sleep most of the time, waiting for a second to pass 32 | printf("%s\t%d \n",argv[1],i); 33 | sleep(1); 34 | i++; 35 | } else if (option==BUSY) { // option is BUSY 36 | //it will simply be running through the loop, consuming cpu 37 | //also a great way to see the effect of renice -n 19 -p PID 38 | // printf("%s %d ",argv[1],i); 39 | // i++; 40 | // BUT all this is in user land 41 | }else { 42 | // make it consume kernel time - some syscall 43 | struct rusage usage; 44 | getrusage(RUSAGE_SELF, &usage); 45 | } 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /misc/sig2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // This code simply prints some global value when SIGUSR1 is delivered to it 7 | // any other signal (eg SIGUSR2) will terminate the proces 8 | 9 | // When SIGUSR2 is used, the handler for SIGUSR1 flips between handler() and SIG_IGN 10 | 11 | int g=99; 12 | 13 | int sig1on=1; 14 | 15 | void handler(int signo) { 16 | if (signo == SIGUSR1) { 17 | printf("received SIGUSR1 when g=%d\n",g); 18 | g++; 19 | } 20 | else if (signo == SIGUSR2) { 21 | if (sig1on) 22 | signal(SIGUSR1, SIG_IGN); 23 | else 24 | signal(SIGUSR1, handler); 25 | sig1on=1-sig1on; 26 | } 27 | } 28 | 29 | void set_my_signal(){ 30 | if (signal(SIGUSR1, handler) == SIG_ERR) { 31 | perror("setting signal failed"); 32 | exit(1); 33 | } 34 | if (signal(SIGUSR2, handler) == SIG_ERR) { 35 | perror("setting signal failed"); 36 | exit(1); 37 | } 38 | } 39 | int main() { 40 | set_my_signal(); 41 | printf("g is at %p\n",&g); 42 | int x=1; 43 | while(1) { 44 | sleep(1); 45 | for(int i=0;i 10 ) x=1; 49 | } 50 | printf("Finished g=%d\n",g); 51 | } 52 | // 53 | /* You may use the following script to get the pid of this process 54 | mypid=`ps -x | grep sig2| grep -v grep | cut -c1-8` 55 | and use this to send 1 and 2 signals to the process. Try with and without USESIGUSR2 defined 56 | while : ; do read; if [ "x$REPLY" == "x1" ]; then kill -s SIGUSR1 $mypid; else kill -s SIGUSR2 $mypid; fi; done 57 | */ 58 | 59 | 60 | -------------------------------------------------------------------------------- /ipc/sem/mysemops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "mysemops.h" 7 | #define MAX 10 8 | #include "configs.h" 9 | 10 | int create_new_sem(int key) { 11 | // Create a semaphore 12 | int semid = semget(key,1,IPC_CREAT|IPC_EXCL|0644); //nsems=1, flags is create 13 | if (semid < 0 ) { 14 | perror("Couldnt create/ acquire:"); 15 | } 16 | return semid; 17 | } 18 | int get_existing_sem(int key) { 19 | // Create a semaphore 20 | int semid = semget(key,1,0); 21 | return semid; 22 | } 23 | // Iniialize a semaphore 24 | // semctl(semid,SEMINDX,CMD,VAL) 25 | void init_sem(int semid, int val){ 26 | if ( semctl(semid,0,SETVAL,val) < 0 ){ 27 | perror("Couldnt initialize:"); 28 | } 29 | } 30 | 31 | int get_info_sem(int semid, struct semid_ds * buf){ 32 | // semctl(semid,SEMINDX,CMD,INFO) 33 | int r = semctl(semid,0,IPC_STAT,buf ); 34 | return r; 35 | } 36 | 37 | int get_val_sem(int semid){ 38 | // getinfo 39 | // semctl(semid,SEMINDX,CMD,INFO) 40 | int r = semctl(semid,0,GETVAL); 41 | return r; 42 | } 43 | 44 | 45 | void lock_down(int semid){ 46 | //struct sembuf un/lock={SEMINDX,SEMOP(+1 or -1),IPC_NOWAIT?} 47 | struct sembuf wait_and_acquire_op={0,-1,0}; 48 | semop(semid,&wait_and_acquire_op,1); 49 | } 50 | 51 | void free_up(int semid){ 52 | //struct sembuf un/lock={SEMINDX,SEMOP(+1 or -1),IPC_NOWAIT?} 53 | struct sembuf free_and_signal_op={0,1,0}; 54 | semop(semid,&free_and_signal_op,1); 55 | } 56 | 57 | void remove_sem(int semid){ // Remove semaphore from the system 58 | int r = semctl(semid,0,IPC_RMID); 59 | } 60 | -------------------------------------------------------------------------------- /files/flush.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // which test read or write ? 5 | #define DOREADTEST 0 6 | 7 | // for write test use write vs printf ? 8 | #define USEWRITE 0 9 | 10 | // when using printf, do you want to flush after printf before fork? 11 | #define USEFLUSH 1 12 | #define FLUSHCMD fflush(stdout) 13 | 14 | 15 | int forked_read(),forked_write(); 16 | 17 | int main(int argc, char * argv[]){ 18 | if ( DOREADTEST ) 19 | forked_read(); 20 | else 21 | forked_write(); 22 | } 23 | 24 | int forked_read(){ 25 | // check read buffering 26 | int i1; 27 | 28 | printf("Test read buffering\n"); 29 | // read and print first number in the file 30 | FILE * f = fopen("/tmp/myfile","r"); 31 | fscanf(f,"%d ",&i1); 32 | printf("1st integer before fork: %d.. waiting for an enter... \n",i1); 33 | 34 | // wait and then fork 35 | getchar(); 36 | int r = fork(); 37 | 38 | // read the second number from the file and print 39 | fscanf(f,"%d ",&i1); 40 | printf("Next From %d: , %d\n",getpid(),i1); 41 | 42 | fclose(f); 43 | } 44 | 45 | int forked_write(){ 46 | int i1; 47 | // Try with printf vs try with write 48 | if (USEWRITE == 1 ) 49 | write(1,"Test write buffers: before fork().. ",35); 50 | else { 51 | printf("Test printf buffers: flush=%d before fork().. ",USEFLUSH); 52 | if (USEFLUSH) 53 | FLUSHCMD; 54 | } 55 | 56 | // Use without flush and try both printf and write above 57 | 58 | int r = fork(); 59 | if (r == 0 ) { // This is child 60 | printf("From C %d ",getpid()); 61 | sleep(2); // Just to see from Parent first 62 | }else{ 63 | printf("From P %d ",getpid()); 64 | } 65 | printf("\n"); 66 | } 67 | -------------------------------------------------------------------------------- /docs/build/Makefile3: -------------------------------------------------------------------------------- 1 | # A more DETAILED Makefile 2 | # We probably need very little beyond what is here 3 | # We can always to do with a simpler Makefile 4 | # ---------------- definitions -------------- 5 | EXEC=hello_world printpid 6 | CC=gcc 7 | CFLAGS= 8 | DEPS = hello_world.h 9 | # These are the .o files from which 10 | # hello_world executable is built 11 | HWOBJS= hello_world.o 12 | 13 | # These are the .o files from which 14 | # printpid xecutable is built 15 | POBJS= printpid.o 16 | 17 | # ---------------- first target to catch all executables ----- 18 | # default target is this first one 19 | all: $(EXEC) 20 | 21 | # ---------------- object files -------------- 22 | # This time we first build .o from .c and then create the 23 | # executables from the .o 24 | # objects(.o) : Here is a tricky shorthand to build all objs 25 | # "%.o depends on the corresponding %.c and 26 | # the files listed in DEPS 27 | # In the build command 28 | # $@ is the left side of the ":" 29 | # $< is the first thing on the right of the ":" 30 | %.o: %.c $(DEPS) 31 | $(CC) -c -o $@ $< $(CFLAGS) 32 | 33 | # ---------------- executables -------------- 34 | # In the build command note a little trick 35 | # The $^ refers to all the stuff on the 36 | # right of the ":" 37 | hello_world: $(HWOBJS) 38 | $(CC) -o $@ $^ 39 | 40 | printpid: $(POBJS) 41 | $(CC) -o $@ $^ 42 | 43 | # ---------------- utilities -------------- 44 | # cleanup utility 45 | 46 | clean: 47 | rm -f $(EXEC) $(HWOBJS) $(POBJS) 48 | 49 | # for fun just try make help 50 | 51 | help: 52 | echo " make clean to remove executables, objs \n" "make all to build executables" 53 | -------------------------------------------------------------------------------- /ipc/sem/shm_consumer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "mysemops.h" 5 | #include "safe_ops.h" 6 | #include "configs.h" 7 | 8 | int main(){ 9 | struct mystruct * s; // pointer to shh 10 | struct semid_ds buf; // needed for status from sem 11 | int semid; 12 | int shmid; 13 | int x; 14 | semid=get_existing_sem(SEM_KEY_VAL); 15 | lock_down(semid); 16 | // first one to acquire lock will (a) create the shm & (b) initialize shm 17 | get_info_sem(semid,& buf); 18 | if (buf.sem_otime == 0 ){ 19 | printf("Firstone\n"); 20 | // I am the first one to get the semaphore 21 | // (a) create the shm 22 | shmid = shmget(SHM_KEY_VAL,sizeof(struct mystruct),IPC_CREAT|IPC_EXCL|0644); 23 | s=shmat(shmid, (void * )NULL, 0); 24 | // (b) initializ the shm 25 | s->free=s->used=0; 26 | // (c) free up the lock 27 | free_up(semid); 28 | } else { 29 | // I am not the first 30 | // (a) get the shm 31 | shmid = shmget(SHM_KEY_VAL,sizeof(struct mystruct),0644); 32 | s=shmat(shmid, (void * )NULL, 0); 33 | // (b) free up the lock 34 | free_up(semid); 35 | } 36 | 37 | int semid_empty_slot=get_existing_sem(SEM_KEY_EMPTY_SLOT); 38 | printf("ID SEM EMPTY %d; val = %d\n", 39 | semid_empty_slot,get_val_sem(semid_empty_slot)); 40 | int semid_filled_slot=get_existing_sem(SEM_KEY_FILLED_SLOT); 41 | printf("ID SEM FILLED %d; val = %d\n", 42 | semid_filled_slot,get_val_sem(semid_filled_slot)); 43 | // safely read 10 successive numbers and then quit 44 | // for(int i=0;i<10;i++) { 45 | while (1) { 46 | lock_down(semid_filled_slot); 47 | int x = safely_get(s,semid); 48 | printf("%d \n",x); 49 | free_up(semid_empty_slot); 50 | } 51 | // } 52 | shmdt(s); 53 | } 54 | -------------------------------------------------------------------------------- /misc/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | Some miscellaneous files to try things out 3 | 4 | FILES 5 | check-endian.c checks the endian-ness of the CPU 6 | ./check-endian [-] 7 | 8 | gtotd.c read the comment in the program - to understand vdso 9 | 10 | address.c print addresses of functions and variables 11 | 12 | sig.c simple signal handler example 13 | sig2.c simple signal handler example extended to flip the way SIGUSR1 is handled 14 | 15 | mmap-simple.c simple use of mmap to create anon 16 | and file mapped regions in memory 17 | Mmap-test-file: A file used by mmap-simple.c 18 | mmap1.c simple use of mmap with flags 19 | 20 | showlim.c a program to display configs and limits 21 | 22 | eratoshenes.c a program to compute primes using two 23 | slightly different implementations. 24 | Intention is to show how to use getrusage 25 | for timing. 26 | 27 | Trivial programs to try out by disassembling, stracing, ltracing etc 28 | printpid.c 29 | reading.c 30 | fact.c 31 | x.c 32 | y.c 33 | - objdump -d to see the assembly 34 | dump of the final executable 35 | - objdump -s to see contents of all sections 36 | - also try gcc -S to see the assembly output 37 | - look inside this for syscalls 38 | - try again with -static compiler option 39 | 40 | Generate exceptions... strace it to see what happened 41 | divbyzero.c 42 | touch_bad_memory.c 43 | 44 | 45 | Tracing programs: 46 | 1. strace ./a.out to see syscalls as they are made 47 | 2. ltrace -S ./a.out to see both library and system calls 48 | NB: gcc -no-pie while compiling before using ltrace. 49 | 3. gdb ./a.out 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ipc/sockets/udp_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "commons.h" 11 | 12 | #define BUFFSIZE 100 13 | 14 | int main() { 15 | int sockfd; 16 | char rcvstr[BUFFSIZE]; 17 | char sendstr[50] = "Client PID is %d\n"; 18 | struct sockaddr_in srv_add; 19 | int len; 20 | 21 | int pid=(int)getpid(); 22 | int l =sprintf(sendstr,"Client PID is %d\n",pid); 23 | sendstr[l]='\0'; // now it is a string, so we can do strlen 24 | 25 | 26 | // Creating socket file descriptor 27 | if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { 28 | perror("socket creation failed"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | //memset(&srv_add, 0, sizeof(srv_add)); 33 | fillzero(srv_add); 34 | 35 | // Filling server information 36 | srv_add.sin_family = AF_INET; 37 | srv_add.sin_port = htons(SRV_PORT); 38 | srv_add.sin_addr.s_addr = INADDR_ANY; 39 | 40 | 41 | printf("Sending to server...\n"); 42 | int n = sendto(sockfd, (const char *)sendstr, strlen(sendstr), 43 | MSG_CONFIRM, (const struct sockaddr *) &srv_add, 44 | sizeof(srv_add)); 45 | if ( n < 0 ){ 46 | perror("cli:sendto()"); 47 | exit(1); 48 | } 49 | printf("...Done!\n"); 50 | 51 | printf("Receiving from server...\n"); 52 | n = recvfrom(sockfd, (char *)rcvstr, BUFFSIZE, 53 | MSG_WAITALL, (struct sockaddr *) &srv_add, 54 | &len); 55 | if ( n < 0 ){ 56 | perror("cli:sendto()"); 57 | exit(1); 58 | } 59 | printf("...Received!\n"); 60 | 61 | rcvstr[n] = '\0'; 62 | printf("Message got from server : %s\n", rcvstr); 63 | 64 | close(sockfd); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /ipc/sockets/udp_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "commons.h" 11 | #define BUFFSIZE 100 12 | 13 | // Driver code 14 | int main() { 15 | int sockfd; 16 | char rcvstr[BUFFSIZE]; 17 | char sendstr[50] = "Server Message\n"; 18 | struct sockaddr_in cli_add, myadd; // rcv cli_add, fill myadd for bind 19 | 20 | // Creating socket file descriptor 21 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 22 | if(sockfd < 0 ) { 23 | perror("socket()"); 24 | exit(1); 25 | } 26 | 27 | fillzero(cli_add); 28 | fillzero(myadd); 29 | 30 | myadd.sin_family = AF_INET; 31 | myadd.sin_addr.s_addr = INADDR_ANY; 32 | myadd.sin_port = htons(SRV_PORT); 33 | 34 | int r = bind(sockfd, (struct sockaddr *)&myadd, 35 | sizeof(myadd)); 36 | if( r < 0 ) 37 | { 38 | perror("bind failed"); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | 43 | int len = sizeof(myadd); 44 | 45 | printf("Receiving from client...\n"); 46 | r = recvfrom(sockfd, (char *)rcvstr, BUFFSIZE-1, 47 | MSG_WAITALL, ( struct sockaddr *) &cli_add, 48 | &len); // get rcvstr, cli_add, read/write: len 49 | if ( r < 0 ) { 50 | perror("recvfrom()"); 51 | exit(1); 52 | } 53 | printf("....Received\n"); 54 | rcvstr[r] = '\0'; 55 | printf("Message got from client: %s\n", rcvstr); 56 | 57 | printf("Sending to client...\n"); 58 | r = sendto(sockfd, (char *)sendstr, strlen(sendstr), 59 | MSG_CONFIRM, (const struct sockaddr *) &cli_add, 60 | len); // use cli_add, len 61 | if ( r < 0 ) { 62 | perror("sendto()"); 63 | exit(1); 64 | } 65 | printf("...Done!"); 66 | 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /files/file_as_a_lock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | // Global 9 | static char * lockfile="lockfile"; 10 | int create_and_acquire_lock(int *fd){ 11 | // return value 12 | // 0 succesfully created, fd is the file descriptor 13 | // 1 unsuccessful 14 | *fd=open(lockfile,O_CREAT|O_EXCL|O_RDWR,S_IRWXU); 15 | if ((*fd) < 0 ) { 16 | if ( errno == EEXIST ) { 17 | printf(" create_and_aquire(): file already exists\n"); 18 | return 1 ; // File already exists 19 | } 20 | perror("open failed unexpectedly "); 21 | exit (1); 22 | 23 | } 24 | return 0 ; // Created a new File 25 | } 26 | void remove_lockfile(){ 27 | int r = unlink(lockfile); 28 | if ( r < 0 ) { 29 | perror("RemoveLockfile() failed "); 30 | exit(1); 31 | } 32 | } 33 | void delete_and_release_lock(int fd){ 34 | close(fd); 35 | remove_lockfile(); // cheating 36 | } 37 | int main(){ 38 | int r; 39 | int fd; 40 | int successes=0; 41 | int i; 42 | for (i = 0 ; i < 10 ; i++) { 43 | printf("Attempting:...\n"); 44 | r = create_and_acquire_lock(&fd); 45 | if (r==0) { //successfully created and acquired 46 | printf(" %d %d: Success, Got it! busy now... \n", i, (int) getpid()); 47 | sleep(5); 48 | delete_and_release_lock(fd); 49 | printf(" ..Done\n"); 50 | successes++; 51 | sleep(3); // simulating some fixed time work 52 | 53 | } else { // unsuccessful in creating 54 | printf(" %d %d: **FAILED**\n", i, (int) getpid()); 55 | // retry 56 | int x=random()%3; 57 | sleep(x); // wait for a random time before retrying 58 | } 59 | 60 | } 61 | printf("Succeeded %d out of %d times\n",successes,i); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /ipc/sockets/udp_echo_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "commons.h" 11 | #define BUFFSIZE 100 12 | 13 | // Driver code 14 | int main() { 15 | int sockfd; 16 | char rcvstr[BUFFSIZE]; 17 | char sendstr[500] = "Server Message\n"; 18 | struct sockaddr_in cli_add, myadd; // rcv cli_add, fill myadd for bind 19 | 20 | // Creating socket file descriptor 21 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 22 | if(sockfd < 0 ) { 23 | perror("socket()"); 24 | exit(1); 25 | } 26 | 27 | fillzero(cli_add); 28 | fillzero(myadd); 29 | 30 | myadd.sin_family = AF_INET; 31 | myadd.sin_addr.s_addr = INADDR_ANY; 32 | myadd.sin_port = htons(SRV_PORT); 33 | 34 | int r = bind(sockfd, (struct sockaddr *)&myadd, 35 | sizeof(myadd)); 36 | if( r < 0 ) 37 | { 38 | perror("bind failed"); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | 43 | int len = sizeof(myadd); 44 | 45 | while(1){ 46 | printf("Receiving from client...\n"); 47 | r = recvfrom(sockfd, (char *)rcvstr, BUFFSIZE-1, 48 | MSG_WAITALL, ( struct sockaddr *) &cli_add, 49 | &len); // get rcvstr, cli_add, read/write: len 50 | if ( r < 0 ) { 51 | perror("recvfrom()"); 52 | exit(1); 53 | } 54 | printf("....Received\n"); 55 | rcvstr[r] = '\0'; 56 | printf("Message got from client: %s\n", rcvstr); 57 | strcpy(sendstr,rcvstr); 58 | printf("Sending to client...\n"); 59 | r = sendto(sockfd, (char *)sendstr, strlen(sendstr), 60 | MSG_CONFIRM, (const struct sockaddr *) &cli_add, 61 | len); // use cli_add, len 62 | if ( r < 0 ) { 63 | perror("sendto()"); 64 | exit(1); 65 | } 66 | printf("...Done!\n"); 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /misc/mallocing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define HEAP 1 6 | #define STACK 0 7 | int heap_or_stack = HEAP; 8 | 9 | #define LEN 4096 // 4K?, 4M Bytes 10 | #define SLEEP 1 11 | #define WAIT 0 12 | long datalen=LEN; 13 | int sleep_or_wait=WAIT; 14 | 15 | int run_test(){ 16 | char * large=NULL; 17 | char * prev =NULL; 18 | for( int cnt=0; 1 ; cnt++) { 19 | prev=large; 20 | if (sleep_or_wait == SLEEP) 21 | sleep(1); 22 | else { 23 | int n; 24 | while( (n = getchar()) != '\n') { 25 | if ( n == 'l' ) // increase datalen 4K->4M->4G 26 | datalen=datalen*1024; 27 | if ( n == 'h' ) 28 | heap_or_stack=HEAP; 29 | if ( n == 's' ) 30 | heap_or_stack=STACK; 31 | } 32 | } 33 | if ( heap_or_stack == HEAP ) { 34 | // Allocate datalen bytes on heap 35 | large=(char * ) malloc(datalen); 36 | // print the return address 37 | printf("now at %3d ->%p\n",cnt,large); 38 | if(cnt==0) continue; 39 | printf("\t diff is %ld\n",large-prev); 40 | // Notice that though we are allocating 41 | // 4KiBytes the difference is a bit (16B) more! 42 | // Possibly the extra space to manage the allocated 4096 bytes 43 | // Use the pmap command on another terminal to check when 44 | // the heap [anon] grows 45 | } else { // STACK 46 | int large[datalen]; 47 | printf("Stacked %ld\n",datalen); 48 | run_test(); 49 | } 50 | } 51 | 52 | } 53 | void print_help(){ 54 | printf( 55 | "Program expects user to hit enter each time before an\n" \ 56 | " allocation. Additionally the following is useful:\n" \ 57 | " l to allocated 1024 times more memory (default is 4KiB)\n" \ 58 | " h to allocate on the heap space (default)\n" \ 59 | " s to allocate on the stack\n" 60 | ); 61 | } 62 | int main(){ 63 | print_help(); 64 | run_test(); 65 | } 66 | -------------------------------------------------------------------------------- /procs/sched_info.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #define YIELD 10 | 11 | void main(){ 12 | // What scheduler policy is my system using for me? 13 | int mypid=getpid(); 14 | printf("Getting my schduler policy: "); 15 | int sdlr = sched_getscheduler(mypid); 16 | switch (sdlr){ 17 | // Normal policies 18 | case SCHED_OTHER: 19 | printf("SCHED_OTHER\n"); 20 | break; 21 | /* My system doesnt support these normal mode scheduler policies 22 | case SCHED_BATCH: 23 | printf("SCHED_BATCH\n"); 24 | break; 25 | case SCHED_IDLE: 26 | printf("SCHED_IDLE\n"); 27 | break; 28 | */ 29 | // real time (high static priority) policies 30 | case SCHED_FIFO: 31 | printf("SCHED_FIFO\n"); 32 | break; 33 | case SCHED_RR: 34 | printf("SCHED_RR\n"); 35 | break; 36 | default: 37 | printf("Unknown policy %d\n",sdlr); 38 | } 39 | 40 | // What is the possible priority range 41 | int max = sched_get_priority_max(SCHED_FIFO); 42 | int min = sched_get_priority_min(SCHED_FIFO); 43 | printf("Allowed priority range for policy %d %d\n",max,min); 44 | 45 | // What scheduler policy parameter (in particular the priority=nice) 46 | printf("Getting scheduler parameters for policy:\n"); 47 | struct sched_param param; 48 | sched_getparam(mypid,¶m); 49 | 50 | 51 | printf(" param.sched_priority %d\n",param.sched_priority); 52 | errno=0; 53 | printf(" Process nice value %d\n",getpriority(PRIO_PROCESS,0)); 54 | if(errno==-1) 55 | printf("**Error in getpriority(PRIO_PROCESS,...\n"); 56 | errno=0; 57 | printf(" User nice value %d\n",getpriority(PRIO_USER,0)); 58 | if(errno==-1) 59 | printf("**Error in getpriority(PRIO_USER,...\n"); 60 | } 61 | -------------------------------------------------------------------------------- /ipc/sem/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | This directory contains files that illustrate use of 3 | sysVipc semaphores. 4 | 5 | FILE DESCRIPTIONS 6 | mysemops.h :: Desclaration of a simplified interface 7 | to semaphore operations 8 | mysemops.c :: Implementation of a simplified interface 9 | to semaphores 10 | 11 | The other file use the above library to create simple examples 12 | 1. sem_ctl.c :: A sample implementation of semaphore 13 | operations. Usable as commandline standalone 14 | 15 | 2. A producer consumer implementation with shared memory 16 | safe_ops.c :: safe implementations of put and get 17 | using semaphores. 18 | shm_producer.c :: A producer that writes 19 | shm_consumer.c :: A consumer that reads 20 | 21 | shm_ctl.c :: Implementing a simple shared memory 22 | structure for the producer and consumer 23 | 24 | RUNNING 25 | ./shm_ctl -h on how to create a new shared memory structure 26 | for the producer/consumer example, 27 | initialize it and monitor it. 28 | ./sem_ctl -h on how to create a new semaphore 29 | initialize it and monitor it. 30 | Use these for the producer/consumer problem as below 31 | // setup the shared memory 32 | ./shm_ctl -n 8888; ./shm_ctl -i 8888 33 | // setup the three semaphores 34 | ./sem_ctl -n 7777; ./sem_ctl -i 7777 1 # (mutex) 35 | ./sem_ctl -n 7776; ./sem_ctl -i 7776 2 # (empty slots) 36 | ./sem_ctl -n 7775; ./sem_ctl -i 7775 0 # (filled slots) 37 | 38 | ./pr # (multiple executions of the producer) 39 | ./cn # (multiple executions of the consumer) 40 | 41 | NB: 42 | These are implemented 'quick and dirty'. 43 | In reality 44 | * check the return values to make sure the operations worked 45 | as intended 46 | * else report perror() and exit(1). 47 | * Template if (ret = do_sem_or_shm_func(args) < 0) { 48 | * perror("This func():"); 49 | * exit(1); 50 | * } 51 | 52 | 53 | -------------------------------------------------------------------------------- /procs/README: -------------------------------------------------------------------------------- 1 | System Calls and exceptions 2 | =========================== 3 | syscallC.c Making a syscall from C calls WRITE(2) 4 | syscall.s Making a syscall from assembly calls WRITE(2) & EXIT(2) 5 | exceptions.c Experiment with a few different exceptions, 6 | run with strace 7 | 8 | 9 | See time spent in Kernel and User mode 10 | ====================================== 11 | loopy.c Creating processes that loop with or without sleep 12 | to see how they consume cpu. 13 | Use ./loopy sleepy to use sleep(2) to consume 14 | little time. 15 | Use ./loopy busy to consume all time in user space. 16 | Use ./loopy kernel to force it to consume kernel time. 17 | Additionally use it with the time(1) command to see usage 18 | You can also use top and ps -l to see time it uses 19 | Also good to check CPU allocation within 20 | an autogroup *like created by a TTY. 21 | 22 | Getting and setting priorty and scheduling policy 23 | ====================================================== 24 | priority_ops.c 25 | sched_info.c 26 | sched_prioritychange.c 27 | sched_policychange.c : use -h or --help to see what the options are 28 | 29 | 30 | Using fork(2), exec(2) and wait(2) 31 | ================================== 32 | simple_getpid.c Just a call to get the pid 33 | simple_exec.c A first intro to exec() 34 | simple_fork.c A first intro to fork() 35 | shell.c A very simple shell - combining the above ideas 36 | zomB.c To create a zombie process 37 | fork_and_termC.c To see what happens when child is terminated 38 | (but not yet reaped) 39 | fork_and_termP.c To see what happens when parent is terminated 40 | fork_experiment.c To see some experiment with IO buffers and addresses 41 | reparent.c To create a process which gets re-parented - 42 | - similar to fork_and_termP.c 43 | 44 | 45 | Experimenting with fd dup(2) 46 | ============================ 47 | duper.c Experimenting with the dup(fd) to see what happens 48 | -------------------------------------------------------------------------------- /ipc/sockets/unx_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "commons.h" 11 | 12 | int main(int argc, char * argv[]){ 13 | // declare socket vars 14 | int l_sock, conn_sock; 15 | int r; 16 | struct sockaddr_un local, remote; 17 | int remote_size=sizeof(remote); 18 | char str[100]; 19 | char suffix[100]="Sever message "; 20 | 21 | 22 | fillzero(local); 23 | // get an internet socket 24 | l_sock=socket(AF_UNIX, SOCK_STREAM , 0); 25 | if (l_sock < 0 ){ 26 | perror("socket():"); 27 | exit(1); 28 | } 29 | 30 | // define a structure with a local address and 31 | // parameters for server port 32 | local.sun_family = AF_UNIX; 33 | strcpy(local.sun_path,UNIX_SOCK_PATH); 34 | 35 | // associate the server socket to the address and port above 36 | r = bind(l_sock,(struct sockaddr *)&local, sizeof(local)); 37 | if (r < 0 ){ 38 | perror("bind():"); 39 | exit(1); 40 | } 41 | 42 | // set the socket to listening for an incoming connection request 43 | r = listen(l_sock,1); 44 | if (r < 0 ){ 45 | perror("listen():"); 46 | exit(1); 47 | } 48 | 49 | // The below part repeats for each new connection 50 | int j=0; 51 | int i=0; 52 | while(1){ 53 | fillzero(remote); 54 | // wait for a connection ... get a new "full" sock 55 | conn_sock=accept(l_sock,(struct sockaddr *)&remote,&remote_size); 56 | if (conn_sock < 0 ){ 57 | perror("accept():"); 58 | exit(1); 59 | } 60 | // send 61 | sprintf(str,"%s %u %d\n",suffix,getpid(),i++); 62 | r = send(conn_sock,str,strlen(str),0); 63 | if (r < 0 ){ 64 | perror("send():"); 65 | exit(1); 66 | } 67 | // receive 68 | r = recv(conn_sock,str,100,0); 69 | if (r < 0 ){ 70 | perror("recv():"); 71 | exit(1); 72 | } 73 | printf("Got %2d: %s\n",j,str); 74 | j++; 75 | // close the new sock 76 | close(conn_sock); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /misc/eratosthenes.c: -------------------------------------------------------------------------------- 1 | // computing the primes upto a certain limit 2 | #include 3 | #include 4 | #include 5 | /* 6 | struct timeval { 7 | time_t tv_sec; seconds 8 | suseconds_t tv_usec; microseconds 9 | }; 10 | */ 11 | struct { 12 | struct timeval start; 13 | struct timeval end; 14 | } times; 15 | void set_time_start(){ 16 | struct rusage usage; 17 | int r = getrusage(RUSAGE_SELF , &usage); 18 | times.start=usage.ru_utime; 19 | } 20 | void set_time_end(){ 21 | struct rusage usage; 22 | int r = getrusage(RUSAGE_SELF , &usage); 23 | times.end=usage.ru_utime; 24 | } 25 | long get_time_usage(){ 26 | return times.end.tv_sec*1000000+times.end.tv_usec 27 | - times.start.tv_sec*1000000+-times.start.tv_usec; 28 | } 29 | 30 | 31 | #define METHOD 2 32 | #define LIMITN 100000 // Look for primes under this limit 33 | #define ASIZE 20000 // This will hold all the primes 34 | int main() 35 | { 36 | 37 | struct { 38 | long int rem; 39 | long int prime; 40 | } factor[ASIZE]; 41 | int idx=0, n, isprime, j; 42 | set_time_start(); 43 | for(n=2;n 2 | #include 3 | #include 4 | #include 5 | #include "configs.h" 6 | #include "safe_ops.h" 7 | #include "mysemops.h" 8 | #include 9 | #define SHM_KEY_VAL 8888 10 | #define SEM_KEY_VAL 7777 11 | #define SEM_KEY_EMPTY_SLOT 7776 12 | #define SEM_KEY_FILLED_SLOT 7775 13 | #define SLOW_DOWN 1 14 | int main(){ 15 | struct mystruct * s; // pointer to shh 16 | struct semid_ds buf; // needed for status from sem 17 | int semid; 18 | int shmid; 19 | semid=get_existing_sem(SEM_KEY_VAL); 20 | lock_down(semid); 21 | // first one to acquire lock will (a) create the shm & (b) initialize shm 22 | get_info_sem(semid, &buf); 23 | printf("buf.sem_otime = %ld\n", buf.sem_otime); 24 | if (buf.sem_otime == 0 ){ 25 | printf("Firstone\n"); 26 | // I am the first one to get the semaphore 27 | // (a) create the shm 28 | shmid = shmget(SHM_KEY_VAL,sizeof(struct mystruct),IPC_CREAT|IPC_EXCL|0644); 29 | s=shmat(shmid, (void * )NULL, 0); 30 | // (b) initializ the shm 31 | s->free=s->used=0; 32 | // (c) free up the lock 33 | free_up(semid); 34 | } else { 35 | // I am not the first 36 | // (a) get the shm 37 | shmid = shmget(SHM_KEY_VAL,sizeof(struct mystruct),0644); 38 | s=shmat(shmid, (void * )NULL, 0); 39 | // (b) free up the lock 40 | free_up(semid); 41 | } 42 | 43 | // s = shmat(shmid, (void * )NULL, 0); 44 | //srand(23); 45 | srand(time(NULL)); 46 | int salt=rand()%100; // salt should be a randome from 0..99 47 | salt=salt*100; 48 | int semid_empty_slot=get_existing_sem(SEM_KEY_EMPTY_SLOT); 49 | int semid_filled_slot=get_existing_sem(SEM_KEY_FILLED_SLOT); 50 | // safely add 10 successive numbers and then quit 51 | // for(int i=salt;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "commons.h" 10 | 11 | int main(int argc, char * argv[]){ 12 | // declare socket vars 13 | int l_sock, conn_sock; 14 | int r; 15 | struct sockaddr_in local, remote; 16 | int remote_size=sizeof(remote); 17 | char str[100]; 18 | char suffix[50]="Sever message "; 19 | 20 | 21 | fillzero(local); 22 | // get an internet socket 23 | l_sock=socket(AF_INET, SOCK_STREAM , 0); 24 | if (l_sock < 0 ){ 25 | perror("socket():"); 26 | exit(1); 27 | } 28 | 29 | // define a structure with a local address and 30 | // parameters for server port 31 | local.sin_family = AF_INET; 32 | local.sin_addr.s_addr = htonl(INADDR_ANY); 33 | local.sin_port = htons( SRV_PORT ); 34 | 35 | // associate the server socket to the address and port above 36 | r = bind(l_sock,(struct sockaddr *)&local, sizeof(local)); 37 | if (r < 0 ){ 38 | perror("bind():"); 39 | exit(1); 40 | } 41 | 42 | // set the socket to listening for an incoming connection request 43 | r = listen(l_sock,1); 44 | if (r < 0 ){ 45 | perror("listen():"); 46 | exit(1); 47 | } 48 | 49 | // The below part repeats for each new connection 50 | int j=0; 51 | int i=0; 52 | while(1){ 53 | fillzero(remote); 54 | // wait for a connection ... get a new "full" sock 55 | conn_sock=accept(l_sock,(struct sockaddr *)&remote,&remote_size); 56 | if (conn_sock < 0 ){ 57 | perror("accept():"); 58 | exit(1); 59 | } 60 | // send 61 | sprintf(str,"%s %u %d\n",suffix,getpid(),i++); 62 | r = send(conn_sock,str,strlen(str),0); 63 | if (r < 0 ){ 64 | perror("send():"); 65 | exit(1); 66 | } 67 | // receive 68 | r = recv(conn_sock,str,100,0); 69 | if (r < 0 ){ 70 | perror("recv():"); 71 | exit(1); 72 | } 73 | printf("Got %2d: %s\n",j,str); 74 | j++; 75 | // close the new sock 76 | close(conn_sock); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /pthreads/update_balance.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define SLEEPTIME 10000 10 | #define MAX 20 11 | #define NTHRD 100 // keep it even 12 | 13 | int gettid(); 14 | 15 | //Normally balance=balance-100 is one statement 16 | //However to illustrate the problem better we can break it up 17 | // into multiple statements 18 | //#define ONESTATEMENT 19 | 20 | 21 | 22 | struct timespec random_time(){ 23 | struct timespec ts; 24 | ts.tv_sec=0; 25 | ts.tv_nsec=random()%SLEEPTIME; 26 | return ts; 27 | } 28 | 29 | 30 | int balance = 0; 31 | 32 | 33 | void * update_decrementer(void * tid){ 34 | struct timespec ts=random_time(); 35 | nanosleep(&ts,NULL); 36 | 37 | #ifdef ONESTATEMENT 38 | balance = balance-100; 39 | #else 40 | int ax =balance; 41 | ax = ax-100; 42 | nanosleep(&ts,NULL); 43 | balance=ax; 44 | #endif 45 | 46 | 47 | return NULL; 48 | } 49 | 50 | void * update_incrementer( void * tid){ 51 | struct timespec ts=random_time(); 52 | nanosleep(&ts,NULL); 53 | 54 | 55 | #ifdef ONESTATEMENT 56 | balance=balance+100; 57 | #else 58 | int ax =balance; 59 | ax = ax+100; 60 | nanosleep(&ts,NULL); 61 | balance=ax; 62 | #endif 63 | 64 | return NULL; 65 | } 66 | 67 | 68 | int main(int argc, char * argv[]){ 69 | pthread_t tid[NTHRD]; // tid is not an integer... non portable structure pointer type 70 | 71 | // Initialize 72 | srand(getpid()); 73 | 74 | for(int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "myincludes.h" 8 | 9 | void main1(){ 10 | 11 | char string[]="Hellow world\n"; 12 | char errstr[]="EE\n"; 13 | // write(1,string,strlen(string)); 14 | 15 | // to open and write to a new file : 16 | // int newfd = open("tempfile",O_CREAT|O_RDWR,S_IRWXU); 17 | 18 | // duplicate the stdout as a new fd 19 | int newfd = dup(1); 20 | close(1); 21 | printf("newfd = %d \n",newfd);//shouldnt work~ but.. 22 | int r = fflush(stdout); 23 | fprintf(stderr,"newfd Found %d ", r); 24 | write(newfd,string,strlen(string)); 25 | 26 | // write(newfd,string,strlen(string)); 27 | // int r = write(newfd,string,strlen(string)); 28 | // printf("Return value is %d",r); 29 | } /* more below */ 30 | 31 | void main2(){ 32 | char string[]="Hellow world\n"; 33 | char errstr[]="EE\n"; 34 | write(1,string,strlen(string)); 35 | int fd = dup(1); 36 | int r = fork(); 37 | if ( r == 0 ){ 38 | close(1); 39 | write(1,errstr,strlen(errstr)); 40 | exit(0); 41 | } else if ( r > 0 ) { 42 | int s; 43 | wait(&s); 44 | write(1,string,strlen(string)); 45 | } else 46 | { 47 | perror("fork(): "); 48 | exit(1); 49 | } 50 | 51 | 52 | } 53 | 54 | void main3() 55 | { 56 | char string[]="Hellow world\n"; 57 | 58 | // to open a new file : 59 | int newfd = open("tempfile",O_CREAT|O_RDWR,S_IRWXU); 60 | // create a newfd that also points to the same place as newfd 61 | // and "here is the trick" - make its fd 1 (over writing the old 1) 62 | int duplicate = dup2(newfd,1); 63 | close(newfd); 64 | 65 | // write(1,string,strlen(string)); 66 | printf("%s",string); 67 | 68 | } 69 | 70 | void main4(){ 71 | // delayed write and sync 72 | char string[]="Hellow World\n"; 73 | // to open an existing file : 74 | int fd = open("permfile",O_WRONLY); 75 | // Write to that file 76 | write(fd,string,strlen(string)); 77 | sleep(20); 78 | close(fd); 79 | 80 | } 81 | 82 | 83 | void main(){ 84 | main4(); 85 | } 86 | -------------------------------------------------------------------------------- /ipc/sockets/conc_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "commons.h" 8 | 9 | void test_send_recv(int conn_sock){ 10 | char str[200]; 11 | char suffix[50]="Sever message "; 12 | // send and receive 5 messages 13 | int i=0; 14 | while(1) { 15 | int r; 16 | 17 | // receive 18 | r = recv(conn_sock,str,100,0); 19 | if (r < 0 ){ 20 | perror("recv():"); 21 | exit(1); 22 | } 23 | if (r == 0 ){ 24 | // client closed connection (EOF) 25 | printf("Server %u: Client exited, connection closed\n",getpid()); 26 | exit(0); 27 | } 28 | str[r]='\0'; 29 | printf("Server %u recvd: %s\n",getpid(),str); 30 | 31 | // send 32 | sprintf(str,"%s from pid %u # %d\n",suffix,getpid(),i++); 33 | r = send(conn_sock,str,strlen(str),0); 34 | if (r < 0 ){ 35 | perror("send():"); 36 | exit(1); 37 | } 38 | sleep(1); 39 | } 40 | } 41 | 42 | 43 | int main(int argc, char * argv[]){ 44 | // declare socket vars 45 | int l_sock, conn_sock; 46 | int r; 47 | struct sockaddr_in local, remote; 48 | int remote_size; 49 | char str[100]; 50 | strcpy(str,"Server message\n"); 51 | // 52 | l_sock=socket(AF_INET, SOCK_STREAM , 0); 53 | if (l_sock < 0 ){ 54 | perror("socket():"); 55 | exit(1); 56 | } 57 | // 58 | fillzero(local); 59 | local.sin_family = AF_INET; 60 | local.sin_addr.s_addr = INADDR_ANY; 61 | local.sin_port = htons( SRV_PORT ); 62 | 63 | r = bind(l_sock,(struct sockaddr *)&local, sizeof(local)); 64 | if (r < 0 ){ 65 | perror("bind():"); 66 | exit(1); 67 | } 68 | r = listen(l_sock,1); 69 | if (r < 0 ){ 70 | perror("listen():"); 71 | exit(1); 72 | } 73 | // The below part repeats for each new connection 74 | while(1){ 75 | fillzero(remote); remote_size = sizeof(remote); 76 | conn_sock=accept(l_sock,(struct sockaddr *)&remote,&remote_size); 77 | if (conn_sock < 0 ){ 78 | perror("accept():"); 79 | exit(1); 80 | } 81 | if ( (r = fork()) < 0 ){ 82 | perror("fork():"); 83 | exit(1); 84 | } else if ( r == 0 ) { 85 | // if child then do the send_recv activity 86 | close(l_sock); 87 | test_send_recv(conn_sock); 88 | exit(1); 89 | } else // if parent then simply close the socket and go for next client 90 | close(conn_sock); 91 | sleep(1); 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /misc/mmap-simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define EG_ANON 0 12 | #define EG_FILE 1 13 | #define FILENAME "Mmap-test-file" 14 | 15 | int test_type = EG_FILE; 16 | 17 | void pmap_file(){ 18 | printf("FILE:Check my pmap at start:\npmap %d; " \ 19 | "make sure file named %s exists\n",getpid(),FILENAME); 20 | getchar(); 21 | printf("Continuing...\n"); 22 | int fd=open(FILENAME,O_RDWR); 23 | if (fd < 0 ) { 24 | perror("Opening File "FILENAME" failed"); 25 | exit(1); 26 | } 27 | char * new_region = mmap(NULL, 4096, 28 | /* readable,writeable */ PROT_READ|PROT_WRITE, 29 | /* shared among procs, file mapped */ MAP_SHARED, 30 | /* fd and offset */ fd, 0); 31 | if (new_region == MAP_FAILED ) { 32 | perror("mmap for new_region"); 33 | exit(1); 34 | } 35 | printf("Check my pmap at after mapping:\npmap %d\n",getpid()); 36 | getchar(); 37 | printf("Continuing...\n"); 38 | int i; 39 | char s[10]; 40 | strncpy(s,new_region,5); 41 | s[5]='\0'; 42 | printf("new_region is at %p and contains: %s\n",new_region, s); 43 | /* also try writing 44 | char hello[]="hello"; 45 | strcpy(new_region,hello); 46 | printf("new_region changed, see file\n"); 47 | printf("Notice that all this is virtual address space\n"); 48 | i = msync(new_region,5,MS_SYNC); 49 | if( i < 0 ) 50 | perror("msync"); 51 | munmap(new_region,4096); 52 | */ 53 | 54 | } 55 | void pmap_anon(){ 56 | printf("ANON:Check my pmap at start:\npmap %d\n",getpid()); 57 | getchar(); 58 | printf("Continuing...\n"); 59 | char * new_region = mmap(NULL, 4096, 60 | /* readable and writable */ PROT_READ|PROT_WRITE, 61 | /* shared among procs, not file mapped */ MAP_PRIVATE |MAP_ANONYMOUS, 62 | /* no fd and offset */ -1, 0); 63 | if (new_region == MAP_FAILED ) { 64 | perror("mmap for new_region"); 65 | exit(1); 66 | } 67 | printf("Check my pmap at after mapping:\npmap %d\n",getpid()); 68 | getchar(); 69 | printf("Continuing...\n"); 70 | int i; 71 | for(i=0;i<10;i++) 72 | new_region[i]='0'+i; 73 | new_region[i]='\0'; 74 | printf("new_region is at %p contains: %s\n",new_region, new_region); 75 | printf("Notice that all this is virtual address space\n"); 76 | } 77 | 78 | void main(){ 79 | if (test_type == EG_FILE) 80 | pmap_file(); 81 | else 82 | pmap_anon(); 83 | } 84 | -------------------------------------------------------------------------------- /files/check-fileinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | struct stat sb; 16 | 17 | if (argc != 2) { 18 | fprintf(stderr, "Usage: %s \n", argv[0]); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | if (lstat(argv[1], &sb) == -1) { 23 | perror("lstat"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | printf("ID of containing device: [%lx,%lx]\n", 28 | (long) major(sb.st_dev), (long) minor(sb.st_dev)); 29 | 30 | printf("File type: "); 31 | 32 | switch (sb.st_mode & S_IFMT) { 33 | case S_IFBLK: printf("block device\n"); break; 34 | case S_IFCHR: printf("character device\n"); break; 35 | case S_IFDIR: printf("directory\n"); break; 36 | case S_IFIFO: printf("FIFO/pipe\n"); break; 37 | case S_IFLNK: printf("symlink\n"); break; 38 | case S_IFREG: printf("regular file\n"); break; 39 | case S_IFSOCK: printf("socket\n"); break; 40 | default: printf("unknown?\n"); break; 41 | } 42 | 43 | printf("I-node number: %ld\n", (long) sb.st_ino); 44 | 45 | printf("Mode: %lo (octal)\n", 46 | (unsigned long) sb.st_mode); 47 | 48 | printf("Link count: %ld\n", (long) sb.st_nlink); 49 | printf("Ownership: UID=%ld GID=%ld\n", 50 | (long) sb.st_uid, (long) sb.st_gid); 51 | 52 | printf("Preferred I/O block size: %ld bytes\n", 53 | (long) sb.st_blksize); 54 | printf("File size: %lld bytes\n", 55 | (long long) sb.st_size); 56 | printf("Blocks allocated: %lld\n", 57 | (long long) sb.st_blocks); 58 | 59 | 60 | printf("Last status change: %s", ctime(&sb.st_ctime)); 61 | printf("Last file access: %s", ctime(&sb.st_atime)); 62 | printf("Last file modification: %s", ctime(&sb.st_mtime)); 63 | 64 | exit(EXIT_SUCCESS); 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /pthreads/README: -------------------------------------------------------------------------------- 1 | ABOUT 2 | This is about pthreads 3 | 4 | FILES 5 | simple.c This just creates a pthread a joins 6 | see what happens when you do a ps 7 | You can ^Z and then look at ps -eLF 8 | Look for the PID/PPID/LWP/NLWP columns 9 | what happens when one of them exits 10 | 11 | other things to try with this file: 12 | pthread_self(); returns the threads on pthread_t 13 | pthread_equal(pthread_t,pthread_t) compares the two pthread_ts 14 | pthread_cancel(pthread_t) cancels 15 | (causes to potentially pthread_exit()) the thread 16 | 17 | update_balance.c 18 | This creates multiple threads to update a balance 19 | You can configure number of threads too 20 | This demonstrates race. 21 | nanosleep is introduced to increase chance of race. 22 | update_balance_mutex.c 23 | You can turn on/off mutex 24 | This is used to demonstrate that mutexes avoid 25 | race. 26 | 27 | find_some_primes.c 28 | This is two threads - one producing numbers 29 | The other checking it is prime 30 | Extending this to multiple producers or consumers 31 | requires more synchronisation! 32 | 33 | find_some_primes_2r.c 34 | This like the above but an additional reader. 35 | Demonstrates race. 36 | nanosleep is used to increase chance of race. 37 | 38 | find_some_primes_mutex.c 39 | This is like the above with 2 readers. 40 | Demonstrates use of mutex to avoid race. 41 | 42 | find_some_primes_cv.c 43 | This is like the above with 2 readers. 44 | Demonstrates use of cond vars to avoid busy wait. 45 | 46 | find_some_primes_cv_many.c 47 | This is like the above, using cv. 48 | code is rewritten a bit. 49 | Deals with an arbitrary number of readers and 50 | writers. 51 | Demonstrates use of cond_broadcast. 52 | 53 | prod_con.c This is an implementation of the producer 54 | consumer problem using pthreads and synchronisation 55 | 56 | Also uses: 57 | safe_ops.c / safe_ops.h : Simplified implementation of put/get 58 | 59 | RUNNING 60 | ./simple for the simple.c example 61 | 62 | ./update_balance 63 | Creates 50 threads by default 64 | 65 | ./pc for the producer-consumer example. Change 66 | # threads if you wish by editing prod_con.c 67 | 68 | ./find_some_primes 69 | This will create two threads. 70 | You can change MAX to see one of them wait 71 | for the other. 72 | 100 items are output. * indicates non-prime 73 | ./find_some_primes_2r 74 | With nanosleep enabled you can see it 75 | doesn't generate theright count of outputs. 76 | Then careful study shows some are duplicate! 77 | Clearly a race on "rear"! 78 | 79 | 80 | -------------------------------------------------------------------------------- /pthreads/find_some_primes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define SLEEPTIME 100 10 | #define NEXT(X) ((X==MAX-1) ? 0 :X+1) 11 | #define END_OF_INPUT -1 12 | int gettid(); 13 | 14 | // Purpose: 15 | // This program shows how two threads can use a common resource - a 16 | // FIFO queue co-operatively 17 | // One is a writer( main() ) and one is a reader( read_item() ) 18 | // The writer only modifies "front" and the reader only modifies "rear" 19 | // They need to co-operate because the queue is small and so it can get full 20 | 21 | // A simple FIFO queue on an array of size MAX 22 | #define MAX 20 23 | int front=0; 24 | int rear=0; 25 | int number[MAX]; 26 | 27 | int genRN(){ 28 | while(1){ 29 | int r = random()%10000; 30 | if (r >1000 ) { 31 | return r; 32 | } 33 | } 34 | } 35 | 36 | int isprime(int n) { 37 | for(int i=2;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define SLEEPTIME 10000 10 | #define MAX 20 11 | #define NTHRD 100 // keep it even 12 | 13 | int gettid(); 14 | 15 | //Normally balance=balance-100 is one statement 16 | //However to illustrate the problem better we can break it up 17 | // into multiple statements 18 | //#define ONESTATEMENT 19 | 20 | // 21 | #define USEMUTEX 22 | 23 | struct timespec random_time(){ 24 | struct timespec ts; 25 | ts.tv_sec=0; 26 | ts.tv_nsec=random()%SLEEPTIME; 27 | return ts; 28 | } 29 | 30 | 31 | int balance = 0; 32 | 33 | #ifdef USEMUTEX 34 | pthread_mutex_t mymutex; 35 | void init_mutex(){ 36 | if (pthread_mutex_init(&mymutex, NULL) != 0) { 37 | printf("Failed to init mutex\n"); 38 | exit(1); 39 | } 40 | } 41 | #endif 42 | 43 | void * update_decrementer(void * tid){ 44 | struct timespec ts=random_time(); 45 | nanosleep(&ts,NULL); 46 | 47 | #ifdef USEMUTEX 48 | pthread_mutex_lock(&mymutex); 49 | #endif 50 | 51 | #ifdef ONESTATEMENT 52 | balance = balance-100; 53 | #else 54 | int ax =balance; 55 | ax = ax-100; 56 | nanosleep(&ts,NULL); 57 | balance=ax; 58 | #endif 59 | 60 | 61 | #ifdef USEMUTEX 62 | pthread_mutex_unlock(&mymutex); 63 | #endif 64 | return NULL; 65 | } 66 | 67 | void * update_incrementer( void * tid){ 68 | struct timespec ts=random_time(); 69 | nanosleep(&ts,NULL); 70 | #ifdef USEMUTEX 71 | pthread_mutex_lock(&mymutex); 72 | #endif 73 | 74 | 75 | #ifdef ONESTATEMENT 76 | balance=balance+100; 77 | #else 78 | int ax =balance; 79 | ax = ax+100; 80 | nanosleep(&ts,NULL); 81 | balance=ax; 82 | #endif 83 | 84 | 85 | #ifdef USEMUTEX 86 | pthread_mutex_unlock(&mymutex); 87 | #endif 88 | return NULL; 89 | } 90 | 91 | 92 | int main(int argc, char * argv[]){ 93 | pthread_t tid[NTHRD]; // tid is not an integer... non portable structure pointer type 94 | 95 | // Initialize 96 | srand(getpid()); 97 | #ifdef USEMUTEX 98 | init_mutex(); 99 | #endif 100 | 101 | for(int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "safe_ops.h" 7 | 8 | #define SLEEPTIME 1 9 | #define NUMCONSUMERS 2 10 | #define NUMPRODUCERS 5 11 | 12 | // Declare all glabal shared stuff 13 | // 1. Data structure 14 | struct mystruct s; // PS: This includes a mutex too! 15 | // Perhaps we could include the CVs as well? 16 | // 2. Conds Mutex for the list 17 | pthread_cond_t emptyslot_cond, filledslot_cond; 18 | 19 | 20 | void * thread_consumer(void * n){ 21 | int t = (int) n + 1; 22 | 23 | while(1){ 24 | // acquire mutex on the buffer 25 | pthread_mutex_lock(&s.mutex); 26 | while (ISEMPTY(s)) { // if not empty, then greedily consume 27 | // wait till there is a FILLED element in the buffer 28 | pthread_cond_wait(&filledslot_cond,&s.mutex); 29 | } 30 | // read that element & update indexes 31 | int x = get(&s); 32 | // signal anyone waiting for EMPTY condition 33 | pthread_cond_signal(&emptyslot_cond); 34 | // release mutex 35 | pthread_mutex_unlock(&s.mutex); 36 | printf("C #%2d v%4d \n",t,x); 37 | } 38 | return NULL ; 39 | } 40 | 41 | void * thread_producer(void * n){ 42 | int t=(int ) n + 1; 43 | int i=0; 44 | //int salt=rand()%100; // salt should be a random from 0..99 45 | int salt=t; 46 | salt=salt*100; 47 | while(1) { 48 | // new value to put 49 | int val=salt+(i%100); 50 | // acquire mutex on the buffer 51 | pthread_mutex_lock(&s.mutex); 52 | // wait till there is a EMPTY element in the buffer 53 | while (ISFULL(s)) { // If not full just go ahead and put 54 | pthread_cond_wait(&emptyslot_cond,&s.mutex); 55 | } 56 | // put new val & update indexes 57 | put(val,&s); 58 | printf("P-------------#%2d v%4d\n",t,val); 59 | // signal anyone waiting for FILLED condition 60 | pthread_cond_signal(&filledslot_cond); 61 | // release mutex 62 | pthread_mutex_unlock(&s.mutex); 63 | i++; 64 | sleep(SLEEPTIME); 65 | } 66 | return NULL ; 67 | } 68 | 69 | 70 | int main(int argc, char * argv[]){ 71 | // initialize randomnumber generator 72 | srand(time(NULL)); 73 | // initialize the mutex and the cvs 74 | pthread_mutex_init(&s.mutex,NULL); 75 | pthread_cond_init(&filledslot_cond,NULL); 76 | pthread_cond_init(&emptyslot_cond,NULL); 77 | 78 | // Initialize the shared data buffer 79 | s.free=s.used=0; // this is empty condition 80 | // but s.free+1==s.used is the full condition 81 | 82 | // Create the consumer threads 83 | int i,r; 84 | pthread_t c_tid[NUMCONSUMERS]; 85 | for(i=0;i < NUMCONSUMERS; i++) 86 | r = pthread_create(&c_tid[i],NULL,thread_consumer,(void *)i); 87 | 88 | // Create the producer threads 89 | pthread_t p_tid[NUMPRODUCERS]; 90 | for(i=0;i < NUMPRODUCERS; i++) 91 | r = pthread_create(&p_tid[i],NULL,thread_producer,(void *)i); 92 | 93 | // This is the main thread. Let it exit, has nothing to do. 94 | printf("Main thread done: Exiting!\n"); 95 | pthread_exit(NULL); 96 | } 97 | -------------------------------------------------------------------------------- /ipc/shm-posix/shm_ctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "common.h" 10 | 11 | void print_help(char * argv[]){ 12 | printf("%s [-n] : The optoinal u argument means do not initialize\n",argv[0]); 13 | printf("option: choose from:\n"); 14 | printf(" o open shm and map to process\n"); 15 | printf(" p print count value in shm\n"); 16 | printf(" i increment the count value in shm\n"); 17 | printf(" d decrement the count value in shm\n"); 18 | printf(" u unlink the shm\n"); 19 | printf(" c close the shm\n"); 20 | printf(" h print this help message\n"); 21 | printf(" q quit this program\n"); 22 | } 23 | void main(int argc, char *argv[]){ 24 | struct mystruct { 25 | int count; 26 | int val[MAX]; 27 | } * s; 28 | int shm_fd; 29 | int mode=1; // by default initialize 30 | 31 | if (argc > 1 && strcmp(argv[1],"-n")==0){ 32 | printf("Setting uninitialized mode for opening\n"); 33 | mode=0; 34 | } 35 | 36 | printf("My pid is %d\n",getpid()); 37 | printf("Using SHM_NAME for operations is = %s\n",SHM_NAME); 38 | 39 | while(1) { 40 | char options[10]; 41 | scanf("%s",options); 42 | 43 | if (strcmp(options,"q")==0) 44 | exit(0); 45 | 46 | if (strcmp(options,"h")==0){ 47 | print_help(argv); 48 | continue; 49 | } 50 | 51 | if (strcmp(options,"o")==0){ 52 | // create the new shm assuming it doesnt exist 53 | // if it exists, just get an fd to it. Like open() 54 | shm_fd = shm_open(SHM_NAME, O_CREAT|O_RDWR,0644); 55 | if ( shm_fd < 0 ) { 56 | perror("Trying to open shm:"); 57 | exit(1); 58 | } else { 59 | printf("Opened shm; "); 60 | ftruncate(shm_fd, sizeof(struct mystruct)); 61 | } 62 | s = mmap(NULL, sizeof(struct mystruct), PROT_READ | PROT_WRITE, 63 | MAP_SHARED, shm_fd, 0); 64 | if (s == NULL) { 65 | perror("couldn't map new"); 66 | exit(1); 67 | } else { 68 | printf("Mapped shm to address space; "); 69 | } 70 | 71 | if (mode) { 72 | s->count=0; 73 | printf("set count field to 0\n"); 74 | } else 75 | printf("\n"); 76 | continue; 77 | } 78 | // print the content 79 | if (strcmp(options,"p")==0){ 80 | printf("Current Value of count = %d\n",s->count); 81 | continue; 82 | } 83 | // increment the content 84 | if (strcmp(options,"i")==0){ 85 | printf("Incremented count...\n"); 86 | s->count++; 87 | printf("Current Value of count = %d\n",s->count); 88 | continue; 89 | } 90 | // decrement the content 91 | if (strcmp(options,"d")==0){ 92 | printf("Decremented count...\n"); 93 | s->count--; 94 | printf("Current Value of count = %d\n",s->count); 95 | continue; 96 | } 97 | 98 | // to remove the shm ... 99 | if (strcmp(options,"u")==0) 100 | if ( shm_unlink(SHM_NAME) != 0 ) 101 | perror("unlink failed"); 102 | else 103 | printf("unlinked\n"); 104 | 105 | if (strcmp(options,"c")==0) 106 | if ( close(shm_fd) != 0 ) 107 | perror("close failed"); 108 | else 109 | printf("closed\n"); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /misc/showlim.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | /* 8 | * see man sysconf 9 | * These are system limits (not user or group specific) 10 | * 11 | * see man getrlimit 12 | * These are user or process specific resource limits 13 | * 14 | * Just to see system and process limits 15 | */ 16 | 17 | void printhelp(int argc,char * argv[]){ 18 | printf("Usage: %s [-r|-s] NAME\n",argv[0]); 19 | printf("Eg. %s -s PAGESIZE\n",argv[0]); 20 | printf("Eg. %s -r STACK\n",argv[0]); 21 | printf("For more info see - man sysconf ; and - man getrlimit\n"); 22 | } 23 | void syscon(int argc, char * argv[]){ 24 | long var=-1; 25 | for (int i=2; i< argc; i ++){ 26 | char *name=argv[i]; 27 | if (strcmp(name,"ARG_MAX")==0){ 28 | var=_SC_ARG_MAX; 29 | } 30 | if (strcmp(name,"PAGESIZE")==0){ 31 | var=_SC_PAGESIZE; 32 | } 33 | if (strcmp(name,"NUMPHYPAGES")==0){ 34 | var=_SC_PHYS_PAGES; 35 | } 36 | if (var != -1 ){ 37 | int r = sysconf(var); 38 | if ( r < 0 ){ 39 | perror("Calling sysconf"); 40 | exit(1); 41 | } 42 | printf(" %s is %d \n",name,r); 43 | } 44 | } 45 | 46 | } 47 | void reslimit(int argc, char * argv[]){ 48 | long var=-1; 49 | struct rlimit rlim; 50 | for (int i=2; i< argc; i ++){ 51 | char name[20]="RLIMIT_"; 52 | strcat(name,argv[i]); 53 | 54 | if (strcmp(name,"RLIMIT_AS")==0){ 55 | var=RLIMIT_AS; 56 | } 57 | if (strcmp(name,"RLIMIT_CORE")==0){ 58 | var=RLIMIT_CORE; 59 | } 60 | if (strcmp(name,"RLIMIT_CPU")==0){ 61 | var=RLIMIT_CPU; 62 | } 63 | if (strcmp(name,"RLIMIT_DATA")==0){ 64 | var=RLIMIT_DATA; 65 | } 66 | if (strcmp(name,"RLIMIT_FSIZE")==0){ 67 | var=RLIMIT_FSIZE; 68 | } 69 | if (strcmp(name,"RLIMIT_LOCKS")==0){ 70 | var=RLIMIT_LOCKS; 71 | } 72 | if (strcmp(name,"RLIMIT_MEMLOCK")==0){ 73 | var=RLIMIT_MEMLOCK; 74 | } 75 | if (strcmp(name,"RLIMIT_MSGQUEUE")==0){ 76 | var=RLIMIT_MSGQUEUE; 77 | } 78 | if (strcmp(name,"RLIMIT_NICE")==0){ 79 | var=RLIMIT_NICE; 80 | } 81 | if (strcmp(name,"RLIMIT_NOFILE")==0){ 82 | var=RLIMIT_NOFILE; 83 | } 84 | if (strcmp(name,"RLIMIT_NPROC")==0){ 85 | var=RLIMIT_NPROC; 86 | } 87 | if (strcmp(name,"RLIMIT_RSS")==0){ 88 | var=RLIMIT_RSS; 89 | } 90 | if (strcmp(name,"RLIMIT_STACK")==0){ 91 | var=RLIMIT_STACK; 92 | } 93 | if (var != -1 ){ 94 | int r = getrlimit(var,&rlim); 95 | if ( r < 0 ){ 96 | perror("Calling sysconf"); 97 | exit(1); 98 | } 99 | printf(" %15s : cur is %ld\n" 100 | " max is %ld\n", 101 | name,rlim.rlim_cur,rlim.rlim_max); 102 | } 103 | } 104 | printf("Note %ld means RLIM_INFINITY\n",RLIM_INFINITY); 105 | } 106 | 107 | int main(int argc, char * argv[]){ 108 | if (argc == 1 ) { 109 | printhelp(argc,argv); 110 | exit(0); // Nothing to do 111 | } 112 | if (strcmp(argv[1],"-r")==0){ 113 | reslimit(argc,argv); 114 | exit(0); 115 | } 116 | if (strcmp(argv[1],"-s")==0) 117 | syscon(argc,argv); 118 | else 119 | printhelp(argc,argv); 120 | exit(0); 121 | 122 | } 123 | -------------------------------------------------------------------------------- /pthreads/find_some_primes_2r.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define SLEEPTIME 100 10 | #define NEXT(X) ((X==MAX-1) ? 0 :X+1) 11 | #define END_OF_INPUT -1 12 | int gettid(); 13 | struct timespec random_time(){ 14 | struct timespec ts; 15 | ts.tv_sec=0; 16 | ts.tv_nsec= random()%SLEEPTIME; 17 | return ts; 18 | } 19 | // Usage: 20 | // struct timespec ts=random_time(); 21 | // nanosleep(&ts,NULL); 22 | 23 | 24 | // Purpose: 25 | // This program adds an additional reader to find_some_primes.c 26 | // use diff find_some_primes.c find_some_primes_2r.c 27 | // Note that this fails to work as intended! 28 | // A simple FIFO queue on an array of size MAX 29 | #define MAX 20 30 | int front=0; 31 | int rear=0; 32 | int number[MAX]; 33 | 34 | int genRN(){ 35 | while(1){ 36 | int r = random()%10000; 37 | if (r >1000 ) { 38 | return r; 39 | } 40 | } 41 | } 42 | 43 | int isprime(int n) { 44 | for(int i=2;i' to see the output. 2 | // 3 | // Beware, this file will not compile as a C program. 4 | // It is just to see how macros expand 5 | // 6 | // 7 | // For a documentation see 8 | // https://gcc.gnu.org/onlinedocs/cpp/Macros.html#Macros 9 | // 10 | // 11 | // ALWAYS 12 | // 0. Macro definition is setting up a Name <-> Expansion associaiton 13 | // 1. Macro usage causes substituting Name by Expansion 14 | // 2. MACRO is expanded only on usage; during definition it is just kept as is 15 | // 3. After expansion again check if other macros expansions apply 16 | // 4. Dont expand inside quotes (strings) 17 | // In the comments below the arrows '->' are used to indicate 18 | // immediate macro expansion 19 | // There are two types of macros 20 | // TYPE 1 object-like macros 21 | // Expansion = simple replacement 22 | // 23 | #define X 100 24 | o1. X // X -> 100 25 | #define BIG 1 26 | o2. BIG // BIG -> 1 27 | #define MYBIG BIG 28 | o3. MYBIG // MYBIG -> BIG -> 1 (Note two step process) 29 | #define A B // Note that B is undefined 30 | #define B 1 31 | ooo. A // A -> B -> 1 32 | #define L_BIG 2 // L_BIG -> 2 33 | 34 | 35 | // TYPE 2 function-like macros 36 | // Now expansion is in two ordered steps 37 | // step 1. Expand all args 38 | // step 2. Expanded macro with args substituted. 39 | // Exceptions to this order are when # and ## are used in the expansion 40 | #define NAMEIT(X) X 41 | f1. NAMEIT(BIG) // NAMEIT(BIG) -> NAMEIT(1) -> 1 Arg expands first 42 | #define DAY(X) "Today is " X 43 | f2. DAY(X) //-> DAY(100) -> "Today is " 100 Arg expands first 44 | 45 | // Exception 1: In case of # on RHS of function-like 46 | // #X => "X" without further expansion of X 47 | // Note as an exception Arg NOT expanded first if stringized! 48 | #define DDAY(N) "Today is " #N 49 | e1. DDAY(X) // DDAY(X) 50 | // -> "Today is " #X Not the arg not expanded 51 | // -> "Today is " "X" 52 | 53 | // Therefore to expand and quote, take two steps: 54 | #define EDDAY(N) DDAY(N) 55 | e2. EDDAY(X) // EDDAY(X) 56 | // -> EDDAY(100) ->DDAY(100) -> "Today is " #100 57 | // ->"Today is " "100" 58 | 59 | // What happens to string around a string ?? 60 | #define STRINGIT(X) #X 61 | e3. STRINGIT(BIG) // -> #BIG ->"BIG" expand before arg expansion 62 | #define EXPSTRINGIT(X) STRINGIT(X) 63 | e4. EXPSTRINGIT(BIG) // -> EXPSTRINGIT ( 1 ) 64 | // -> STRINGIT(1) -> #1 -> "1" 65 | #define QEXPSTRINGIT(X) EXPSTRINGIT(STRINGIT(X)) 66 | e5. QEXPSTRINGIT(BIG) 67 | // QEXPSTRINGIT(BIG) 68 | // -> QEXPSTRINGIT(1) 69 | // -> EXPSTRINGIT(STRINGIT(1)) 70 | // -> EXPSTRINGIT( "1" ) 71 | // -> STRINGIT("1") 72 | // -> #"1" 73 | // -> "\"1\"" : Notice nice escaping 74 | // of inner quote marks 75 | 76 | // Eception 2: ## is used for concatenation, again DONT expand argument first. 77 | #define CON(X) L_##X 78 | e6. CON(BIG) // CON(BIG) 79 | // ->L_BIG 80 | // ->2 81 | 82 | 83 | // What if argument X occurs with and without #? 84 | // first treat it as an exception and expand macro first 85 | #define MYDAY(N) #N N 86 | e7. MYDAY(X) // -> #X X expand body first 87 | // -> "X" 100 88 | 89 | -------------------------------------------------------------------------------- /docs/gdb-sheet: -------------------------------------------------------------------------------- 1 | Some useful gdb commands one can use to investigate what the code 2 | that is running looks like, in addition to of course debugging real code. 3 | 4 | NOTE: Before using gdb, make sure to compile code with a '-g' flag and 5 | you may want to experiment by turning off optimizations. 6 | 7 | A SUPER QUICK INTRO with a sample run 8 | 9 | Here is a sample run, you should be able to do this with a very simple program, 10 | perhaps it a main() and one more function with local variables. 11 | 12 | $ gcc -g myprog.c # will compile the program so that you can use gdb on it meaningfully 13 | $ gdb a.out 14 | (gdb) l # will list program source 15 | (gdb) l # will list program source from given lineno 16 | (gdb) l # will list program source from given function 17 | (gdb) b # set a breakpoint at the given lineno 18 | (gdb) b # set a breakpoint at the given function 19 | (gdb) run # Run the program from beginning and stop at the next breakpoint 20 | (gdb) n # will execute the current line and stop after that 21 | (gdb) s # like n, but if its a call it steps into the function and stop 22 | (gdb) p # will print the value of the given variable 23 | (gdb) finish # will run to the end of the current function and print the return value 24 | (gdb) info locals # will print all local and their values 25 | (gdb) i lo # same as info locals 26 | (gdb) info frame # will print information about the current stack frame 27 | (gdb) i f # same as info frame 28 | (gdb) set variable = # will assign a value to a variable 29 | (gdb) cont # will continue execution from the current line till the next breakpoint 30 | (gdb) bt # will print backtrace ie sequence of frames upto current 31 | # with set to 'full' it will print locals too. 32 | 33 | 34 | NB: 35 | It is also possible to view the program lines as it is running: 36 | At the gdb prompt say: 37 | (gdb) tui enable # At this point you can see a split window showing your program in execution as you type the gdb commands. 38 | Another way to do this is to use emacs and the M-x gdb command 39 | 40 | 41 | 42 | OTHER USEFUL COMMANDS: 43 | 44 | * Listng lines of code: 45 | (gdb) list [n] 46 | * Listing lines starting at the current ip 47 | (gdb) list * $rip 48 | * looking at assembler code 49 | (gdb) disassemble ; lists assembly of the current function 50 | (gdb) disassemble * $rip 51 | (gdb) disassemble 52 | * Stack frames listing 53 | (gdb) bt 54 | (gdb) bt full 55 | * more informatio with info 56 | (gdb) info frame [n] ; information abouta stack frame (0 is topmost) 57 | (gdb) info locals ; information about locals and args 58 | (gdb) info args 59 | * Dumping the contents of memory 60 | (gdb) x/nfu 61 | eg x/20xw $rip ; examine 20 hexformatted words starting at $rip 62 | x/20db $rbp-12 ; useful to examine something moved into $rbp-0xc 63 | x/20db 0x55000000 ; dump content of memory byte wise starting at 0x5500 64 | 65 | More details list of commands 66 | https://ccrma.stanford.edu/~jos/stkintro/Useful_commands_gdb.html 67 | Also see a quick overview 68 | https://www.geeksforgeeks.org/gdb-step-by-step-introduction/ 69 | -------------------------------------------------------------------------------- /ipc/sem-posix/sem_ctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | // Default semaphore name 13 | #define DEF_SEM_NAME "/sem-1" 14 | 15 | 16 | void print_help(char * argv[]){ 17 | printf("%s [-r] : The optional -r argument means remove the sem\n",argv[0]); 18 | printf("option: choose from:\n"); 19 | printf(" i n set initial value for next opento the number n\n"); 20 | printf(" n s set semaphore name to the string s (must follow convention)\n"); 21 | printf(" o open sem\n"); 22 | printf(" p post sem\n"); 23 | printf(" w wait sem\n"); 24 | printf(" c close sem\n"); 25 | printf(" u unlink sem\n"); 26 | printf(" v get sem value\n"); 27 | printf(" h print this help message\n"); 28 | printf(" q quit this program\n"); 29 | } 30 | void main(int argc, char *argv[]){ 31 | sem_t * sem=NULL; 32 | int mode=1; // by default initialize 33 | unsigned int init_value=0; 34 | char sem_name[100]=DEF_SEM_NAME; 35 | 36 | printf("My pid is %d\n",getpid()); 37 | printf("Using sem_name for operations is = %s\n",sem_name); 38 | printf("Get help using \"h\"\n"); 39 | 40 | if (argc > 1 && strcmp(argv[1],"-r")==0){ 41 | printf("Removing existing semaphore, new one will start at set initial value[0]\n"); 42 | sem_unlink(sem_name); 43 | } else 44 | printf("Will reuse any existing semaphore\n"); 45 | 46 | while(1) { 47 | char options[10]; 48 | scanf("%s",options); 49 | 50 | if (strcmp(options,"q")==0) 51 | exit(0); 52 | 53 | if (strcmp(options,"h")==0){ 54 | print_help(argv); 55 | continue; 56 | } 57 | 58 | if (strcmp(options,"i")==0){ 59 | scanf("%u",&init_value); 60 | continue; 61 | } 62 | 63 | if (strcmp(options,"n")==0){ 64 | scanf("%s",sem_name); 65 | continue; 66 | } 67 | 68 | if (strcmp(options,"o")==0){ 69 | // create the new sem assuming it doesnt exist 70 | 71 | sem=sem_open(sem_name,O_RDWR|O_CREAT,0644,init_value); 72 | if (sem == SEM_FAILED ){ 73 | perror("Filled sem creation"); 74 | exit(1); 75 | } else 76 | printf("Opened sem\n"); 77 | continue; 78 | } 79 | 80 | if (strcmp(options,"p")==0){ 81 | // post 82 | int r = sem_post(sem); 83 | if ( r < 0 ) 84 | perror("Post failed"); 85 | else 86 | printf("Post done\n"); 87 | continue; 88 | } 89 | if (strcmp(options,"w")==0){ 90 | // wait 91 | int r = sem_wait(sem); 92 | if ( r < 0 ) 93 | perror("Wait failed"); 94 | else 95 | printf("Wait done\n"); 96 | continue; 97 | } 98 | 99 | if (strcmp(options,"v")==0){ 100 | // Read the value of the semaphore 101 | int r; 102 | if ( sem_getvalue(sem,&r)!= 0 ) 103 | perror("Getvalue failed"); 104 | else 105 | printf("sem value is: %d\n", r); 106 | continue; 107 | } 108 | 109 | if (strcmp(options,"u")==0) 110 | if ( sem_unlink(sem_name) != 0 ) 111 | perror("unlink failed"); 112 | else 113 | printf("unlinked\n"); 114 | 115 | // to close the sem ... 116 | if (strcmp(options,"c")==0) 117 | if ( sem_close(sem) != 0 ) 118 | perror("close failed"); 119 | else 120 | printf("closed\n"); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ipc/shm/shm_ctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common.h" 8 | 9 | void print_help(char * argv[]){ 10 | printf("%s