180 likes | 405 Views
TDC368 UNIX and Network Programming. Week 6: Inter-Process Synchronization Signals Lock-Files. Camelia Zlatea, PhD Email: czlatea@cs.depaul.edu. Discussion. File Redirectation Inter-process Communication via pipe Pipe synchronization Deadlock?
E N D
TDC368UNIX and Network Programming Week 6: • Inter-Process Synchronization • Signals • Lock-Files Camelia Zlatea, PhD Email: czlatea@cs.depaul.edu
Discussion • File Redirectation • Inter-process Communication via pipe • Pipe synchronization • Deadlock? • A deadlock situation can occur when two processes open respectively the two ends of a pipe for writing • Starvation? • Blocking reader / writer for unbounded interval of time • Errors • “Broken Pipe”? SIGPIPE • Process Type • Related process (named or unamed pipes) • Unrelated process (only named pipes) • Pipe vs. File for inter-process communication?
I/O redirection - ex: sort < test.dat > result #include <stdio.h> #include <unistd.h> int main(void) { int fd1, fd2; switch (fork()) { case -1: perror("fork"); break; case 0: if ((fd1 = open("test.dat", O_RDONLY))==1) || (fd2 = open("results", O_WRONLY|O_CREAT|O_TRUNC,0644))==-1) { perror("open failure"); _exit(errno); } /* set standard input from "test.dat" */ if (dup2(fd1,0)==-1) _exit(errno); /* set standard output to "results" */ if (dup2(fd2,1)==-1) _exit(errno); close(fd1); close(fd2); execl("sort","sort"); perror("execl"); exit(errno); } return 0; }
Simulating sleep by using alarm and pause #include <stdio.h> #include <signal.h> #include <unistd.h> void wakeup() { ; }; unsigned int sleep ( unsigned int timer ) { if (sigset(SIGALRM, wakeup)==-1) { perror("sigset"); return 1; } (void)alarm( timer ); (void)pause(); return 0; }
Example: A Producer-Consumer relation void wakeup() { ; }; int main(void) { int fd, n, i; pid_t pid, ppid; char buf[1]; if((fd=open("/tmp/data_file", O_APPEND|O_CREATE, 0640)) <0) exit(1); sigset(SIGTERM,SIG_IGN);/* signal */ ; sigset(SIGINT,SIG_IGN); /* signal */ pid=fork(); switch (pid) { case -1: { perror(“FORK”); exit(1); } case 0: /* child process - Producer */ sigset(SIGUSR1,wakeup); sighold(SIGUSR1); /* block / hold signals SIGUSR1 until sigpause*/ for (i=0; i<=100; i++) { /* sleep a random amount of time */ n = (int)(getpid()%256); srand((unsigned)n); sleep(rand() %5); /* writes a character in file */ sprintf(buf,"%d",i); write(fd, buf,sizeof(buf)); fprintf(stderr,"Producer PID=%d value = %d\n",getpid(), i); ppid=getppid(); kill(ppid, SIGUSR2); sigpause(SIGUSR1); /* pause(); until SIGUSR! received*/ } break;
Example: A Producer-Consumer relation default: /* -parent code - Consumer */ sigset(SIGUSR2,wakeup); sighold(SIGUSR2); /* block / hold signals SIGUSR2 until sigpause*/ for (i=0; i<=100; i++) { /* sleep a random amount of time */ n = (int)(getpid()%256); srand((unsigned)n); sleep(rand() %5); sigpause(SIGUSR2); /* pause(); */ /* reads a character from file */ read(fd, buf,sizeof(buf)); fprintf(stderr,"Consumer PID=%d value=%d\n",getpid(),atoi(buf)); kill(pid, SIGUSR1) } break; } exit(0); }
Provide a mechanism to share data among processes Provide a mechanism to synchronize reading and writing of shared files. Applicable for regular files A process imposes a lock on a file(or record) so that other processes can’t modify the file(record) until it is unlocked by the process. UNIX File/Record Locking
write lock exclusive lock processes are prevented from setting any overlapping read/write locks on the locked region of the file read lock shared lock processes are prevented from setting any overlapping write locks on the locked region of the file UNIX File/Record Locking
mandatory lock enforced by OS kernel example: chmod a+l file_name an erroneous situation: A process sets a mandatory lock on a file and never unlocks it. The file cannot be accessed by any other process until the owner process is either killed or system is re-booted UNIX File/Record Locking
advisory lock processes can still use read or write to access the shared file unless cooperation procedure is followed processes using advisory locks to share a file must cooperate: try to set a lock on the record to be accessed (read or write) if fails to set the lock then: wait and test_again or do_work and test_again if succeeds to set the lock accesses the locked file/record releases the lock UNIX File/Record Locking
System V 4 and POSIX.1 #include <fcntl.h> int fcntl(int fd, int cmd,struct flock fl); cmd: F_SETLK sets a file lock; do not block if failure F_SETLKW sets a file lock blocks until succeeds F_GETLK tests if a file or record is locked and by whom UNIX File/Record Locking
System V 4 and POSIX.1 struct flock { short l_type; /* lock type */ short l+whence; /* rec. ref. */ off_t l_start; /* rec. offset */ off_t l_len; /* rec.length */ pid_t l_pid; /* process ID*/ }; UNIX File/Record Locking
System V 4 and POSIX.1 /* lock type */ F_RDLCK - read/shared lock F_WRLCK - write/exclusive lock F_UNLCK - unlock a record/file /* record reference */ SEEK_CUR - current file pointer SEEK_SET - byte 0 of file SEEK_END - EOF UNIX File/Record Locking
Simulating Semaphores with Lock Files int Pflag(char *file_name, int ntries, int nsec) { int fd; i=0; while ((fd = create(file_name,0)) ==-1 && errno ==EACCES) /* EACCES - file exists, no write permission on it */ if (++i <ntries) sleep(nsec); else return 0; close(fd); /* lock_file created with 0 bytes and no permissions */ if (fd == -1) return 0; else return 1; }
Simulating Semaphores with Lock Files int Vflag(char *file_name) { int i; i = unlink(file_name); if (i==0) return 1; /* success, lock file removed */ if (i==-1) return 0; /* failure, lock file was not removed */ }
Process Synchronizations using Lock Files int main(void) { pid_t p; int i; q, status, nbytes; int fd; char buf[80]; /* parent process opens date file Shared Data File */ if ((fd = open("/tmp/data_file", O_RDONLY|O_CREATE, 0666))<0) { perror("open"); exit(1); } /* parent forks 3 new processes */ for (i=0; i<4; i++) { if (p=fork()) == 0) break; } switch (p) { case 0: /* a child process */ if (Pflag("/tmp/lock_file", 5,10)) { if (nbytes=read(fd,buf,sizeof(buf)))>0) { fprintf(stderr,"PID=%d data=%s\n", getpid(), buf); sleep(10); /* releases the resource - shared file */ Vflag("/tmp/lock_file"); } else fprintf(stderr, "Cannot access data file\n"); break;
Process Synchronizations using Lock Files case -1: /* cannot fork processes */ perror("fork"); exit(1); break; default: /* parent */ while ((q=wait(&status))>0) ; break; } exit(0); }