Inter-Process Communication CS 351: Systems Programming Michael - - PowerPoint PPT Presentation

inter process communication
SMART_READER_LITE
LIVE PREVIEW

Inter-Process Communication CS 351: Systems Programming Michael - - PowerPoint PPT Presentation

Inter-Process Communication CS 351: Systems Programming Michael Saelee <lee@iit.edu> 1 Computer Science Science The OS kernel does a great job of isolating processes from each other 2 Computer Science Science If not, programming


slide-1
SLIDE 1

Inter-Process Communication

CS 351: Systems Programming Michael Saelee <lee@iit.edu>

1

slide-2
SLIDE 2

Computer Science Science

The OS kernel does a great job of isolating processes from each other

2

slide-3
SLIDE 3

Computer Science Science

If not, programming would be much harder!

  • all data accessible (read/write) to world
  • memory integrity not guaranteed
  • control flow unpredictable

3

slide-4
SLIDE 4

Computer Science Science

But processes are more useful when they can exchange data & interact dynamically

4

slide-5
SLIDE 5

Computer Science Science

The original data exchange unit: the file see: BBS, FTP , Napster, BitTorrent

5

slide-6
SLIDE 6

Computer Science Science

But what about dynamic data exchange? e.g., instant messaging, VOIP , MMOGs

6

slide-7
SLIDE 7

Computer Science Science

Demo: shell “pipes”

7

slide-8
SLIDE 8

Computer Science Science

The kernel enforces isolation … so to perform inter-process communication (IPC), must ask kernel for help/assistance

8

slide-9
SLIDE 9

Computer Science Science

Another role for the kernel: errand boy

9

slide-10
SLIDE 10

Computer Science Science

Select IPC mechanisms:

  • 1. signals
  • 2. (regular) files
  • 3. shared memory
  • 4. unnamed & named pipes
  • 5. file locks & semaphores
  • 6. sockets

10

slide-11
SLIDE 11

Computer Science Science

§Common Issues

11

slide-12
SLIDE 12

Computer Science Science

  • 1. link/endpoint creation
  • naming
  • lookup / registry

12

slide-13
SLIDE 13

Computer Science Science

  • 2. data transmission
  • unidirectional/bidirectional
  • single/multi-sender/recipient
  • speed/capacity
  • message packetizing
  • routing

13

slide-14
SLIDE 14

Computer Science Science

  • 3. data synchronization
  • behavior with multiple senders

and/or receivers

  • control: implicit / explicit / none

14

slide-15
SLIDE 15

Computer Science Science

  • 4. access control
  • mechanism
  • granularity

15

slide-16
SLIDE 16

Computer Science Science

§Files

16

slide-17
SLIDE 17

Computer Science Science

in general, regular files are a really lousy mechanism for dynamic IPC

  • ultra-slow backing store (disk)
  • coordinating file positions is tricky

17

slide-18
SLIDE 18

Computer Science Science

int main() { pid_t pid1, pid2; int fd = open("shared.txt", O_CREAT|O_TRUNC|O_RDWR, 0644); if ((pid1 = fork()) == 0) { dup2(fd, 1); execl("/bin/echo", "/bin/echo", "hello", NULL); } if ((pid2 = fork()) == 0) { dup2(fd, 0); execl("/usr/bin/wc", "/usr/bin/wc", "-c", NULL); } waitpid(pid2, NULL, 0); }

Output? … it depends …

18

slide-19
SLIDE 19

Computer Science Science

we won’t be considering regular files as a mechanism for (dynamic) IPC

19

slide-20
SLIDE 20

Computer Science Science

§Shared Memory

20

slide-21
SLIDE 21

Computer Science Science

simple idea: allow processes to share data stored in memory i.e., sidestep memory protection

21

slide-22
SLIDE 22

Computer Science Science

shm... APIs:

  • file descriptor based
  • memory mapped

22

slide-23
SLIDE 23

Computer Science Science

int shm_open(const char *name, int oflag, mode_t mode);

  • returns FD for shared memory
  • may be mapped to temp file (of name)
  • persists until explicitly removed!

int shm_unlink(const char *name);

  • explicitly remove shared memory

FD-based API:

23

slide-24
SLIDE 24

Computer Science Science

#define SHM_NAME "/myshm" /* arbitrary shm identifier */ int shmfd = shm_open(SHM_NAME, O_RDWR|O_CREAT, 0644); write(shmfd, ...); /* writing process */ int shmfd = shm_open(SHM_NAME, O_RDONLY, 0); char buf[N]; read(shmfd, buf, N); /* reading process */

24

slide-25
SLIDE 25

Computer Science Science

int shmget(key_t key, size_t size, int shmflg);

  • returns ID for shm of size

void *shmat(int shmid, const void *shmaddr, int shmflg);

  • returns (local) pointer to shm given ID

int shmdt(const void *shmaddr);

  • detach from shm (but still persists)

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

  • manage existing shm object

memory-mapped API:

25

slide-26
SLIDE 26

Computer Science Science

#define SHM_KEY 0xABCD #define SHM_SIZE 1024 int shmid = shmget(SHM_KEY, /* unique system-wide shm key */ SHM_SIZE, /* size of shm (in bytes) */ IPC_CREAT|0600); /* IPC_CREAT not needed if already exists */ char *shm = shmat(shmid, NULL, 0); /* map shm into my address space */ strcpy(shm, "hello world!"); /* access shm (via pointer) */ shmdt(shm); /* detach from shm (i.e., unmap) */ shmctl(shmid, IPC_RMID, NULL); /* remove shm from system */

26

slide-27
SLIDE 27

Computer Science Science

if shm isn’t removed, it persists … and processes have limited IPC resources!

$ ipcs -mpb IPC status from <running system> as of Thu Oct 18 18:13:07 CDT 2012 T ID KEY MODE OWNER GROUP SEGSZ CPID LPID m 2162688 0x0000abcd --rw------- lee staff 1024 44861 44861 $ ipcrm -m 2162688 # deletes the shared memory object

int shmid = shmget(0xABCD, 1024, IPC_CREAT|0600); ... shmdt(shm_arr); /* but no shmctl(shmid, IPC_RMID, NULL); */

27

slide-28
SLIDE 28

Computer Science Science

shm is the fastest form of IPC;

  • nly overhead = process switch

(unavoidable anyway)

28

slide-29
SLIDE 29

Computer Science Science

int shmid, i; char *shm_arr; if ((pid = fork()) != 0) { shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT|0600); shm_arr = shmat(shmid, NULL, 0); memset(shm_arr, 0, SHM_SIZE); for (i=0; i<SHM_SIZE; i++) { shm_arr[i] = i; } shmdt(shm_arr); shmctl(shmid, IPC_RMID, NULL); } else { shmid = shmget(SHM_KEY, SHM_SIZE, 0600); shm_arr = shmat(shmid, NULL, 0); for (i=0; i<SHM_SIZE; i++) { printf("%d ", shm_arr[i]); } shmdt(shm_arr); } #define SHM_KEY 0xABCD #define SHM_SIZE 5 (error — no output) 0 1 2 3 4 0 0 0 0 0 0 1 0 0 0 0 1 2 0 0

...

29

slide-30
SLIDE 30

Computer Science Science

to fix, we need processes using shared memory to communicate … using another IPC mechanism!

30

slide-31
SLIDE 31

Computer Science Science

writer reader

creates shm “proceed!” writes to shm block for signal block for signal attach to shm read from shm “proceed!” detach from shm detach from shm remove shm

① ② ③

  • ne approach: signals

31

slide-32
SLIDE 32

Computer Science Science

int sig_recvd = 0; void sighandler (int sig) { if (sig == SIGUSR1) sig_recvd = 1; } int main (int argc, char *argv[]) { signal(SIGUSR1, sighandler); /* parent/writer process */ if ((pid = fork()) != 0) { shmid = shmget(SHM_KEY, ..., IPC_CREAT|...); shm_arr = shmat(shmid, ...); for (i=0; i<SHM_SIZE; i++) { shm_arr[i] = i; } kill(pid, SIGUSR1); /* signal child */ while (!sig_recvd) /* block for child signal */ sleep(1); shmdt(shm_arr); shmctl(shmid, IPC_RMID, NULL); } /* child/reader process */ else { while (!sig_recvd) /* block for parent signal */ sleep(1); shmid = shmget(SHM_KEY, ...); shm_arr = shmat(shmid, ...); for (i=0; i<SHM_SIZE; i++) { printf("%d ", shm_arr[i]); } shmdt(shm_arr); kill(getppid(), SIGUSR1); /* signal parent */ }

0 1 2 3 4

① ② ③

32

slide-33
SLIDE 33

Computer Science Science

but wait ...

/* parent/writer process */ if ((pid = fork()) != 0) { ... for (i=0; i<SHM_SIZE; i++) { shm_arr[i] = i; } kill(pid, SIGUSR1); } /* child/reader process */ else { while (!sig_recvd) pause(); ... for (i=0; i<SHM_SIZE; i++) { printf("%d ", shm_arr[i]); } }

we’ve eliminated concurrency! (w.r.t. shm access)

33

slide-34
SLIDE 34

Computer Science Science

writer reader

creates shm block for signal block for signal read from shm write to shm block for signal block for signal read from shm write to shm block for signal

... how about:

34

slide-35
SLIDE 35

Computer Science Science

/* parent/writer process */ if ((pid = fork()) != 0) { ... for (i=0; i<SHM_SIZE; i++) { shm_arr[i] = i; } ... } /* child/reader process */ else { ... for (i=0; i<SHM_SIZE; i++) { printf("%d ", shm_arr[i]); } ... }

still not really good enough … writer should be permitted to write up to SHM_SIZE before stopping

35

slide-36
SLIDE 36

Computer Science Science

writer reader

block for signal read from shm up to N times N writes to shm N × “proceed!”

recall: signals aren’t queued! :-( how about:

36

slide-37
SLIDE 37

Computer Science Science

also, with all this sync overhead, shm isn’t looking so hot anymore

37

slide-38
SLIDE 38

Computer Science Science

§Unnamed Pipes

38

slide-39
SLIDE 39

Computer Science Science

int pipe(int fds[2]); fds[0] is the “reading end” fds[1] is the “writing end”

kernel space fds[0] fds[1]

39

slide-40
SLIDE 40

Computer Science Science

  • buffer of finite size = PIPE_BUF
  • defined in <limits.h>
  • on fourier = 4096

40

slide-41
SLIDE 41

Computer Science Science

  • read blocks for min of 1 byte
  • write blocks until complete
  • writes ≤ PIPE_BUF are atomic
  • can’t be interrupted by other writes

41

slide-42
SLIDE 42

Computer Science Science

  • speed can’t compare to shm!
  • requires copy from user to kernel

buffer, then back to a user buffer

user kernel user

42

slide-43
SLIDE 43

Computer Science Science

int i, j, fds[2]; pipe(fds); /* create pipe */ if (fork() != 0) { /* parent writes */ for (i=0; i<10; i++) { write(fds[1], &i, sizeof(int)); } } else { /* child reads */ for (i=0; i<10; i++) { read(fds[0], &j, sizeof(int)); printf("%d ", j); } } 0 1 2 3 4 5 6 7 8 9

43

slide-44
SLIDE 44

Computer Science Science

int i, n, fds[2]; char buf[80]; char *strings[] = {"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"}; the quick foxoverbrown jumpslazythe dog pipe(fds); for (i=0; i<9; i++) { /* 9 child processes! */ if (fork() == 0) { write(fds[1], strings[i], strlen(strings[i])); exit(0); } } while ((n = read(fds[0], buf, sizeof(buf))) > 0) { write(1, buf, n); printf("\n"); }

44

slide-45
SLIDE 45

Computer Science Science

kernel takes care of buffering & synchronization! (yippee!)

45

slide-46
SLIDE 46

Computer Science Science

back to shell pipes:

$ echo hello | wc 1 1 6

46

slide-47
SLIDE 47

Computer Science Science

int fds[2]; pid_t pid1, pid2; pipe(fds); if ((pid1 = fork()) == 0) { dup2(fds[1], 1); execlp("echo", "echo", "hello", NULL); } if ((pid2 = fork()) == 0) { dup2(fds[0], 0); execlp("wc", "wc", NULL); } waitpid(pid2, NULL, 0); (hangs)

47

slide-48
SLIDE 48

Computer Science Science

key: read on pipe will always block for ≥ 1 byte until writing ends are all closed

48

slide-49
SLIDE 49

Computer Science Science

int fds[2]; pid_t pid1, pid2; pipe(fds); if ((pid1 = fork()) == 0) { dup2(fds[1], 1); execlp("echo", ...); } if ((pid2 = fork()) == 0) { dup2(fds[0], 0); execlp("wc", ...); } waitpid(pid2, NULL, 0);

never sees EOF!

49

slide-50
SLIDE 50

Computer Science Science

1 1 6 if ((pid1 = fork()) == 0) { dup2(fds[1], 1); close(fds[1]); execlp("echo", "echo", "hello", NULL); } close(fds[1]); if ((pid2 = fork()) == 0) { dup2(fds[0], 0); execlp("wc", "wc", NULL); }

50

slide-51
SLIDE 51

Computer Science Science

so … why “unnamed” pipes?

51

slide-52
SLIDE 52

Computer Science Science

int fds[2]; if (fork() == 0) { /* proc 1 */ pipe(fds); write(fds[1], …); }

  • no way for proc 1 and

proc 2 to talk over pipe!

  • identified solely by FDs

– process local

if (fork() == 0) { /* proc 2 */ read(?, …); }

52

slide-53
SLIDE 53

Computer Science Science

§Named Pipes (FIFOs)

53

slide-54
SLIDE 54

Computer Science Science

int mkfifo (const char* path, mode_t perms)

  • creates a FIFO special file at path in

file system

  • open(s) then read & write
  • exhibits pipe semantics!

54

slide-55
SLIDE 55

Computer Science Science

$ mkfifo /tmp/my.fifo $ ls -l /tmp/my.fifo prw------- 1 lee wheel 0 24 Apr 04:13 /tmp/my.fifo $ cat /tmp/my.fifo & [1]+ cat /tmp/my.fifo & $ echo hello > /tmp/my.fifo hello [1]+ Done cat /tmp/my.fifo $ cat /etc/passwd > /tmp/my.fifo & [1]+ cat /etc/passwd >/tmp/my.fifo & $ cat /tmp/my.fifo root:*:0:0:System Administrator:/var/root:/bin/tcsh lee:*:501:20:Michael Lee,,,:/Users/lee:/bin/bash ... [1]+ Done cat /etc/passwd >/tmp/my.fifo $ rm /tmp/my.fifo

55

slide-56
SLIDE 56

Computer Science Science

P1

P2 important limitation: while bi-directional communication is possible; it is half-duplex

56

slide-57
SLIDE 57

Computer Science Science

let’s talk a bit more about synchronization

57

slide-58
SLIDE 58

Computer Science Science

why? so concurrent systems can be made predictable

58

slide-59
SLIDE 59

Computer Science Science

how? so far:

  • wait (limited)
  • kill & signal (lousy)
  • pipe (implicit)

59

slide-60
SLIDE 60

Computer Science Science

some UNIX IPC mechanisms are purpose- built for synchronization

60

slide-61
SLIDE 61

Computer Science Science

§File Locks

61

slide-62
SLIDE 62

Computer Science Science

motivation:

  • process virtual worlds don’t extend to

the file system

  • concurrently modifying files can have

ugly consequences

  • but files are the most widely used form
  • f IPC!

62

slide-63
SLIDE 63

Computer Science Science

a process can acquire a lock on a file, preventing other processes from using it

63

slide-64
SLIDE 64

Computer Science Science

int fcntl(int fd, int cmd, struct flock);

struct flock { short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */ short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */

  • ff_t l_start; /* Starting offset for lock */
  • ff_t l_len; /* Num bytes to lock (0 for all) */

pid_t l_pid; /* PID of process holding lock */ ... }; cmd = { F_GETLK, F_SETLK, F_SETLKW}

test, set, set (wait)

64

slide-65
SLIDE 65

Computer Science Science

important: locks are not preserved across forks! (i.e., a child doesn’t inherit its parent’s locks)

65

slide-66
SLIDE 66

Computer Science Science

int fd, n; struct flock fl; char buf[80]; fd = open("shared.txt", O_RDWR|O_CREAT, 0600); fl.l_type = F_WRLCK; fl.l_whence = 0; fl.l_len = 0; fl.l_pid = getpid(); fcntl(fd, F_SETLK, &fl); /* set write (exclusive) lock */ if (fork() == 0) { fl.l_type = F_RDLCK; fcntl(fd, F_SETLKW, &fl); /* wait for & set read lock */ lseek(fd, 0, SEEK_SET); /* rewind pos */ n = read(fd, buf, sizeof(buf)); write(1, buf, n); } else { sleep(1); /* make child wait */ write(fd, "hello there!", 13); fl.l_type = F_UNLCK; fcntl(fd, F_SETLK, &fl); /* release lock */ } hello there!

66

slide-67
SLIDE 67

Computer Science Science

problem: most file systems only support advisory locking i.e., locks are not enforced!

67

slide-68
SLIDE 68

Computer Science Science

in Linux, mandatory locking is possible, but requires filesystem to support it

68

slide-69
SLIDE 69

Computer Science Science

The implementation of mandatory locking in all known versions of Linux is subject to race conditions which render it unreliable: a write(2) call that overlaps with a lock may modify data after the mandatory lock is acquired; a read(2) call that overlaps with a lock may detect changes to data that were made only after a write lock was

  • acquired. Similar races exist between mandatory locks and mmap(2).

It is therefore inadvisable to rely on mandatory locking.

69

slide-70
SLIDE 70

Computer Science Science

also, file locks are not designed for general- purpose synchronization

70

slide-71
SLIDE 71

Computer Science Science

e.g., what if we want to:

  • allow only 1 of N processes to access

an arbitrary resource?

  • allow M of N processes to access a

resource?

  • control the order in which processes

run?

71

slide-72
SLIDE 72

Computer Science Science

§Semaphores

72

slide-73
SLIDE 73

Computer Science Science

semaphore = synchronization primitive

  • object with associated counter
  • usually init to count ≥ 0

73

slide-74
SLIDE 74

Computer Science Science

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

  • creates semaphore initialized to value

sem_t *sem_open(const char *name, int oflag);

  • retrieves existing semaphore

int sem_wait(sem_t *sem);

  • decrements value; blocks if new value < 0
  • returns 0 on success
  • returns -1 if interrupted without decrementing

int sem_post(sem_t *sem);

  • increments value; unblocks 1 process (if any)
  • returns 0 on success

74

slide-75
SLIDE 75

Computer Science Science

1 “/fred”

sem_t *sem = sem_open("/fred", O_CREAT, 0600, 1);

75

slide-76
SLIDE 76

Computer Science Science

1 “/fred” P1 P2

76

slide-77
SLIDE 77

Computer Science Science

1 “/fred” P1 P2

sem_wait(sem)

77

slide-78
SLIDE 78

Computer Science Science

1 “/fred” P1 P2

sem_wait(sem)

  • 78
slide-79
SLIDE 79

Computer Science Science

“/fred” P1 P2

sem_wait(sem)

  • 79
slide-80
SLIDE 80

Computer Science Science

“/fred” P1 P2

sem_wait(sem)

  • 80
slide-81
SLIDE 81

Computer Science Science

“/fred” P1 P2

sem_wait(sem)

…..

81

slide-82
SLIDE 82

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem)

…..

82

slide-83
SLIDE 83

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem)

…..

  • 83
slide-84
SLIDE 84

Computer Science Science

  • 1

“/fred” P1 P2

sem_wait(sem) sem_wait(sem)

…..

  • 84
slide-85
SLIDE 85

Computer Science Science

  • 1

“/fred” P1 P2

sem_wait(sem) sem_wait(sem)

blocks! (no return)

…..

  • 85
slide-86
SLIDE 86

Computer Science Science

  • 1

“/fred” P1 P2

sem_wait(sem) sem_wait(sem)

…..

86

slide-87
SLIDE 87

Computer Science Science

  • 1

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

…..

87

slide-88
SLIDE 88

Computer Science Science

  • 1

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

…..

++

88

slide-89
SLIDE 89

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

…..

++

89

slide-90
SLIDE 90

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

…..

++

unblocks!

90

slide-91
SLIDE 91

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

…..

++

unblocks!

91

slide-92
SLIDE 92

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

….. ….. …..

92

slide-93
SLIDE 93

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

….. ….. …..

sem_post(sem)

93

slide-94
SLIDE 94

Computer Science Science

“/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

….. ….. …..

sem_post(sem) ++

94

slide-95
SLIDE 95

Computer Science Science

1 “/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

….. ….. …..

sem_post(sem) ++

95

slide-96
SLIDE 96

Computer Science Science

1 “/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

….. ….. …..

sem_post(sem) ++

96

slide-97
SLIDE 97

Computer Science Science

1 “/fred” P1 P2

sem_wait(sem) sem_wait(sem) sem_post(sem)

….. ….. …..

sem_post(sem)

…..

97

slide-98
SLIDE 98

Computer Science Science

/* unsynchronized file writers */ int i, j, fd; fd = open("shared.txt", O_CREAT|O_WRONLY, 0600); for (i=0; i<5; i++) { if (fork() == 0) { } } $ cat shared.txt 01000011223411234532356765475968764798789529869789 for (j='0'; j<='9'; j++) { write(fd, &j, 1); sleep(random() % 3); } exit(0);

98

slide-99
SLIDE 99

Computer Science Science

$ cat shared.txt 01234567890123456789012345678901234567890123456789 /* synchronized file writers */ int i, j, fd; sem_t *mutex = sem_open("/mutex", O_CREAT, 0600, 1); fd = open("shared.txt", O_CREAT|O_WRONLY, 0600); for (i=0; i<5; i++) { if (fork() == 0) { while (sem_wait(mutex) < 0) ; for (j='0'; j<='9'; j++) { write(fd, &j, 1); sleep(random() % 3); } sem_post(mutex); exit(0); } }

99

slide-100
SLIDE 100

Computer Science Science

/* synchronized file writers */ sem_t *mutex = sem_open("/mutex", O_CREAT, 0600, 1); for (i=0; i<5; i++) { if (fork() == 0) { while (sem_wait(mutex) < 0) ; /* write */ sem_post(mutex); exit(0); } } /* unsynchronized file writers */ for (i=0; i<5; i++) { if (fork() == 0) { /* write */ exit(0); } }

100

slide-101
SLIDE 101

Computer Science Science

$ time ./fw-async ./fw-async 0.00s user 0.01s system 0% cpu 11.019 total $ time ./fw-sync ./fw-sync 0.00s user 0.01s system 0% cpu 50.050 total ... for (j='0'; j<='9'; j++) { write(fd, &j, 1); sleep(random() % 3); /* avg sleep = 1 sec */ } ...

101

slide-102
SLIDE 102

Computer Science Science

P1: Iter 0 P2: Iter 0 P2: Iter 1 P1: Iter 1 P1: Iter 2 P2: Iter 2 P1: Iter 3 P1: Iter 4 P2: Iter 3 P2: Iter 4 P1: Iter 5 P2: Iter 5 P1: Iter 6 P1: Iter 7 P1: Iter 8 P1: Iter 9 P2: Iter 6 P2: Iter 7 P2: Iter 8 P2: Iter 9 int i; if (fork() == 0) { /* P1 */ for (i=0; i<10; i++) { sleep(random() % 3); printf("P1: Iter %d\n", i); fflush(stdout); } exit(0); } if (fork() == 0) { /* P2 */ for (i=0; i<10; i++) { sleep(random() % 3); printf("P2: Iter %d\n", i); fflush(stdout); } exit(0); }

102

slide-103
SLIDE 103

Computer Science Science

P1: Iter 0 P2: Iter 0 P1: Iter 1 P2: Iter 1 P2: Iter 2 P1: Iter 2 P1: Iter 3 P2: Iter 3 P2: Iter 4 P1: Iter 4 P1: Iter 5 P2: Iter 5 P1: Iter 6 P2: Iter 6 P1: Iter 7 P2: Iter 7 P1: Iter 8 P2: Iter 8 P1: Iter 9 P2: Iter 9 int i; sem_t *p1_arrived, *p2_arrived; p1_arrived = sem_open("/sem1", O_CREAT, 0600, 0); p2_arrived = sem_open("/sem2", O_CREAT, 0600, 0); if (fork() == 0) { /* P1 */ for (i=0; i<10; i++) { sleep(random() % 3); sem_post(p1_arrived); sem_wait(p2_arrived); printf("P1: Iter %d\n", i); fflush(stdout); } exit(0); } if (fork() == 0) { /* P2 */ for (i=0; i<10; i++) { sleep(random() % 3); sem_post(p2_arrived); sem_wait(p1_arrived); printf("P2: Iter %d\n", i); fflush(stdout); } exit(0); }

103

slide-104
SLIDE 104

Computer Science Science

(hangs) int i; sem_t *p1_arrived, *p2_arrived; p1_arrived = sem_open("/sem1", O_CREAT, 0600, 0); p2_arrived = sem_open("/sem2", O_CREAT, 0600, 0); if (fork() == 0) { /* P1 */ for (i=0; i<10; i++) { sleep(random() % 3); sem_wait(p2_arrived); sem_post(p1_arrived); printf("P1: Iter %d\n", i); fflush(stdout); } exit(0); } if (fork() == 0) { /* P2 */ for (i=0; i<10; i++) { sleep(random() % 3); sem_wait(p1_arrived); sem_post(p2_arrived); printf("P2: Iter %d\n", i); fflush(stdout); } exit(0); }

104

slide-105
SLIDE 105

Computer Science Science

sem_t *mutex = sem_open("/mutex", O_CREAT, 0600, 1); for (i=0; i<5; i++) { if (fork() == 0) { while (sem_wait(mutex) < 0) ; ... sem_post(mutex); exit(0); } } while (wait(NULL) >= 0); sem_close(mutex); sem_unlink("/mutex");

just as with shared memory, semaphores persist when process exits … must unlink

105

slide-106
SLIDE 106

Computer Science Science

there is much, much more to synchronization & concurrency … (coming in CS 450!)

106

slide-107
SLIDE 107

Computer Science Science

§IPC Recap

107

slide-108
SLIDE 108

Computer Science Science

Select IPC mechanisms:

  • 1. signals
  • 2. (regular) files
  • 3. shared memory
  • 4. unnamed & named pipes
  • 5. file locks & semaphores
  • 6. sockets

108

slide-109
SLIDE 109

Computer Science Science

  • ne motive: data communication
  • at one end: shm — fast but no

synchronization

  • at other end: pipes — slower but

implicitly synchronized

109

slide-110
SLIDE 110

Computer Science Science

another motive: synchronization

  • signals: system events
  • file locks (advisory!)
  • semaphores: simple but surprisingly

versatile!

110

slide-111
SLIDE 111

Computer Science Science

so far, just intra-system IPC. coming later, network sockets for inter- system IPC!

111