inter-process communicationcomputer science science int shmget(key_t key, size_t size, int shmflg);...

111
Inter-Process Communication CS 351: Systems Programming Michael Saelee <[email protected]> 1

Upload: others

Post on 05-Jun-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Inter-Process CommunicationComputer 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);

Inter-Process Communication

CS 351: Systems ProgrammingMichael Saelee <[email protected]>

1

Page 2: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

2

Page 3: Inter-Process CommunicationComputer 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);

Computer ScienceScience

If not, programming would be much harder!

- all data accessible (read/write) to world

- memory integrity not guaranteed

- control flow unpredictable

3

Page 4: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

4

Page 5: Inter-Process CommunicationComputer 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);

Computer ScienceScience

The original data exchange unit: the file

see: BBS, FTP, Napster, BitTorrent

5

Page 6: Inter-Process CommunicationComputer 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);

Computer ScienceScience

But what about dynamic data exchange?

e.g., instant messaging, VOIP, MMOGs

6

Page 7: Inter-Process CommunicationComputer 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);

Computer ScienceScience

Demo:

shell “pipes”

7

Page 8: Inter-Process CommunicationComputer 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);

Computer ScienceScience

The kernel enforces isolation

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

8

Page 9: Inter-Process CommunicationComputer 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);

Computer ScienceScience

Another role for the kernel: errand boy

9

Page 10: Inter-Process CommunicationComputer 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);

Computer ScienceScience

Select IPC mechanisms:1. signals2. (regular) files3. shared memory4. unnamed & named pipes5. file locks & semaphores6. sockets

10

Page 11: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§Common Issues

11

Page 12: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

12

Page 13: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

13

Page 14: Inter-Process CommunicationComputer 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);

Computer ScienceScience

3. data synchronization- behavior with multiple senders

and/or receivers- control: implicit / explicit / none

14

Page 15: Inter-Process CommunicationComputer 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);

Computer ScienceScience

4. access control- mechanism- granularity

15

Page 16: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§Files

16

Page 17: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

- ultra-slow backing store (disk)

- coordinating file positions is tricky

17

Page 18: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 19: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

19

Page 20: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§Shared Memory

20

Page 21: Inter-Process CommunicationComputer 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);

Computer ScienceScience

simple idea: allow processes to share data stored in memory

i.e., sidestep memory protection

21

Page 22: Inter-Process CommunicationComputer 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);

Computer ScienceScience

shm... APIs:

- file descriptor based

- memory mapped

22

Page 23: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 24: Inter-Process CommunicationComputer 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);

Computer ScienceScience

#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

Page 25: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 26: Inter-Process CommunicationComputer 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);

Computer ScienceScience

#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

Page 27: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

$ ipcs -mpbIPC status from <running system> as of Thu Oct 18 18:13:07 CDT 2012T ID KEY MODE OWNER GROUP SEGSZ CPID LPIDm 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

Page 28: Inter-Process CommunicationComputer 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);

Computer ScienceScience

shm is the fastest form of IPC;

only overhead = process switch (unavoidable anyway)

28

Page 29: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 30: Inter-Process CommunicationComputer 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);

Computer ScienceScience

to fix, we need processes using shared memory to communicate

… using another IPC mechanism!

30

Page 31: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

one approach: signals

31

Page 32: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 33: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 34: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 35: Inter-Process CommunicationComputer 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);

Computer ScienceScience

/* 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 writeup to SHM_SIZE before stopping

35

Page 36: Inter-Process CommunicationComputer 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);

Computer ScienceScience

writer reader

block for signal

read from shmup to N times

N writes to shm

N × “proceed!”

recall: signals aren’t queued! :-(

how about:

36

Page 37: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

37

Page 38: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§Unnamed Pipes

38

Page 39: Inter-Process CommunicationComputer 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);

Computer ScienceScience

int pipe(int fds[2]);

fds[0] is the “reading end”fds[1] is the “writing end”

kernel space

fds[0]fds[1]

39

Page 40: Inter-Process CommunicationComputer 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);

Computer ScienceScience

- buffer of finite size = PIPE_BUF

- defined in <limits.h>

- on fourier = 4096

40

Page 41: Inter-Process CommunicationComputer 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);

Computer ScienceScience

- read blocks for min of 1 byte

- write blocks until complete

- writes ≤ PIPE_BUF are atomic

- can’t be interrupted by other writes

41

Page 42: Inter-Process CommunicationComputer 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);

Computer ScienceScience

- speed can’t compare to shm!

- requires copy from user to kernel buffer, then back to a user buffer

user

kernel

user

42

Page 43: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 44: Inter-Process CommunicationComputer 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);

Computer ScienceScience

int i, n, fds[2];char buf[80];char *strings[] = {"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"};

thequickfoxoverbrownjumpslazythedog

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

Page 45: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

45

Page 46: Inter-Process CommunicationComputer 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);

Computer ScienceScience

back to shell pipes:

$ echo hello | wc 1 1 6

46

Page 47: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 48: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

48

Page 49: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 50: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 51: Inter-Process CommunicationComputer 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);

Computer ScienceScience

so … why “unnamed” pipes?

51

Page 52: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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 localif (fork() == 0) {

/* proc 2 */ read(?, …);}

52

Page 53: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§Named Pipes (FIFOs)

53

Page 54: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 55: Inter-Process CommunicationComputer 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);

Computer ScienceScience

$ 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

Page 56: Inter-Process CommunicationComputer 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);

Computer ScienceScience

P1 P2

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

56

Page 57: Inter-Process CommunicationComputer 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);

Computer ScienceScience

let’s talk a bit more about synchronization

57

Page 58: Inter-Process CommunicationComputer 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);

Computer ScienceScience

why?

so concurrent systems can be made predictable

58

Page 59: Inter-Process CommunicationComputer 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);

Computer ScienceScience

how?

so far:

- wait (limited)

- kill & signal (lousy)

- pipe (implicit)

59

Page 60: Inter-Process CommunicationComputer 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);

Computer ScienceScience

some UNIX IPC mechanisms are purpose-built for synchronization

60

Page 61: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§File Locks

61

Page 62: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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 of IPC!

62

Page 63: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

63

Page 64: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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 */ off_t l_start; /* Starting offset for lock */ off_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

Page 65: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

65

Page 66: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 67: Inter-Process CommunicationComputer 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);

Computer ScienceScience

problem: most file systems only support advisory locking

i.e., locks are not enforced!

67

Page 68: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

68

Page 69: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 70: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

70

Page 71: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 72: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§Semaphores

72

Page 73: Inter-Process CommunicationComputer 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);

Computer ScienceScience

semaphore = synchronization primitive

- object with associated counter

- usually init to count ≥ 0

73

Page 74: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 75: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

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

75

Page 76: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

P1 P2

76

Page 77: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

P1 P2

sem_wait(sem)

77

Page 78: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

P1 P2

sem_wait(sem)

--

78

Page 79: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

--

79

Page 80: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

--

80

Page 81: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

…..

81

Page 82: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

…..

82

Page 83: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

…..

--

83

Page 84: Inter-Process CommunicationComputer 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);

Computer ScienceScience

-1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

…..

--

84

Page 85: Inter-Process CommunicationComputer 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);

Computer ScienceScience

-1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)blocks!(no return)…

..

--

85

Page 86: Inter-Process CommunicationComputer 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);

Computer ScienceScience

-1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

…..

86

Page 87: Inter-Process CommunicationComputer 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);

Computer ScienceScience

-1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

87

Page 88: Inter-Process CommunicationComputer 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);

Computer ScienceScience

-1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

++

88

Page 89: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

++

89

Page 90: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

++ unblocks!

90

Page 91: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

++ unblocks!

91

Page 92: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

…..

…..

92

Page 93: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

…..

…..

sem_post(sem)

93

Page 94: Inter-Process CommunicationComputer 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);

Computer ScienceScience

0

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

…..

…..

sem_post(sem)

++

94

Page 95: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

…..

…..

sem_post(sem)

++

95

Page 96: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

…..

…..

sem_post(sem)

++

96

Page 97: Inter-Process CommunicationComputer 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);

Computer ScienceScience

1

“/fred”

P1 P2

sem_wait(sem)

sem_wait(sem)

sem_post(sem)

…..

…..

…..

sem_post(sem)

…..

97

Page 98: Inter-Process CommunicationComputer 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);

Computer ScienceScience

/* 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.txt01000011223411234532356765475968764798789529869789

for (j='0'; j<='9'; j++) { write(fd, &j, 1); sleep(random() % 3); } exit(0);

98

Page 99: Inter-Process CommunicationComputer 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);

Computer ScienceScience

$ cat shared.txt01234567890123456789012345678901234567890123456789

/* 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

Page 100: Inter-Process CommunicationComputer 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);

Computer ScienceScience

/* 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

Page 101: Inter-Process CommunicationComputer 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);

Computer ScienceScience

$ 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

Page 102: Inter-Process CommunicationComputer 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);

Computer ScienceScience

P1: Iter 0P2: Iter 0P2: Iter 1P1: Iter 1P1: Iter 2P2: Iter 2P1: Iter 3P1: Iter 4P2: Iter 3P2: Iter 4P1: Iter 5P2: Iter 5P1: Iter 6P1: Iter 7P1: Iter 8P1: Iter 9P2: Iter 6P2: Iter 7P2: Iter 8P2: 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

Page 103: Inter-Process CommunicationComputer 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);

Computer ScienceScience

P1: Iter 0P2: Iter 0P1: Iter 1P2: Iter 1P2: Iter 2P1: Iter 2P1: Iter 3P2: Iter 3P2: Iter 4P1: Iter 4P1: Iter 5P2: Iter 5P1: Iter 6P2: Iter 6P1: Iter 7P2: Iter 7P1: Iter 8P2: Iter 8P1: Iter 9P2: 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

Page 104: Inter-Process CommunicationComputer 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);

Computer ScienceScience

(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

Page 105: Inter-Process CommunicationComputer 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);

Computer ScienceScience

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

Page 106: Inter-Process CommunicationComputer 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);

Computer ScienceScience

there is much, much more to synchronization & concurrency …

(coming in CS 450!)

106

Page 107: Inter-Process CommunicationComputer 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);

Computer ScienceScience

§IPC Recap

107

Page 108: Inter-Process CommunicationComputer 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);

Computer ScienceScience

Select IPC mechanisms:1. signals2. (regular) files3. shared memory4. unnamed & named pipes5. file locks & semaphores6. sockets

108

Page 109: Inter-Process CommunicationComputer 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);

Computer ScienceScience

one motive: data communication

- at one end: shm — fast but no synchronization

- at other end: pipes — slower but implicitly synchronized

109

Page 110: Inter-Process CommunicationComputer 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);

Computer ScienceScience

another motive: synchronization

- signals: system events

- file locks (advisory!)

- semaphores: simple but surprisingly versatile!

110

Page 111: Inter-Process CommunicationComputer 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);

Computer ScienceScience

so far, just intra-system IPC.

coming later, network sockets for inter-system IPC!

111