cs162b: semaphores (and shared memory) jacob t. chan

25
CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Upload: lesley-rodgers

Post on 11-Jan-2016

239 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

CS162B: Semaphores (and Shared Memory)Jacob T. Chan

Page 2: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Pthreads: The Problem

It is not readily available in all systems Windows doesn’t have it

Pthreads only work in the program they are in It won’t work outside of its program

It does not deal with two different programs What if you have two different programs that need to communicate with one

another? Files are okay and useful, but risky (file permissions and overwrites, which lead to

RACE CONDITIONS) Objective: ensure that other shared resources are not accessed simultaneously

Page 3: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Semaphores and Shared Memory

No need to invoke libraries (no more –lpthread)

Use the following headers: #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h>

These headers should be present in any semaphore-shared memory related operation/s

Page 4: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Semaphore

System of visual signaling that uses flags held in both hands

Shared resource

An integer that operates on multiple processes via queue-like system With simultaneous operations running arbitrarily

Includes rest of data that allows facilitates such operations

Page 5: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Implementing Semaphores

int semid; // need to remember this

int key = A_LARGE_CONSTANT; // ex. 1234

int n = 1; // or another number

semid = semget(key, n, IPC_CREAT | 0666);

1 key = 1 semaphore *array*

n = number of elements in the array; if n > existing array size, then it will result in failure.

last argument indicates flags and permissions.

IPC_CREAT = create if necessary

0666 = complete access for everyone (equivalent to chmod 777)

Returns-1 on error. Otherwise, it returns a semaphore ID

Page 6: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

More on semget()

You can use the same key for different programs This will return the same semaphore array At least you won’t use different keys for different arrays

BUT, it is risky You might be using a key that is already in use by another unrelated program Example: running central servers (with the same port, but we aren’t discussing

network socketing YET)

Page 7: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Accessing Semaphores

struct sembuf sema[2]; // perform 2 operations

[0]: operation to wait for semaphore to become 0 (block if another process or thread is accessing the semaphore)

[1]: operation to increment semaphore

int opNum = 2; // like I said, perform 2 operations

Page 8: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Accessing Semaphores

sema[0].sem_num = 0; // index of 1st element in array

sema[0].sem_op = 0; // wait if semaphore != 0

sema[0].sem_flg = SEM_UNDO; //allocate space for undo operation

sema[1].sem_num = 0;

sema[1].sem_op = 1; // increment semaphore by 1

sema[1].sem_flg = SEM_UNDO | IPC_NOWAIT;

If same sem_num, it means that you operate on SAME semaphore in array (which is the usual thing)

Page 9: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Accessing Semaphores

int opResult = semop(semid, sema, opNum);

Will return -1 on error.

SEM_UNDO = Allocate space for an undo operation if process terminates abnormally. Prevents semaphores to be locked forever (until the system reboots)

IPC_NOWAIT = Force error if operation must wait.

Although sema has 2 elements, opNum can be set to 1 if you ONLY need the 1st operation performed (the wait and get blocked operation)

Page 10: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Accessing Semaphores

If sema[0] is run, calling process blocks if semaphore is NOT 0 Implication: another process/thread has control over the semaphore It will not block if semaphore is 0 already Reason: remember it’s the waiting operation?

If it is not blocked anymore, sema[1] will be performed next Semaphore is increased and semop() returns If semop() returns a value that is not -1, then the process has gained control!

Page 11: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

After the access…

Do what you want to do!

The process shared has access already to the shared memory that semaphore was guarding

Obviously, SHARED resource is involved, so after the process does its thing, it must release the resource (otherwise, a deadlock occurs)

Illustration: Using an object you just borrowed

Page 12: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

The Release

opNum = 1; // perform 1 operation

sema[0].sem_num = 0; // index of 1st element in array

sema[0].sem_op = -1; // decrement semaphore by 1

sema[0].sem_flg = SEM_UNDO | IPC_NOWAIT;

opResult = semop(semid, sema, opNum);

Note: There are many other ways to indicate control of a semaphore.

Page 13: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

The Release

After releasing, the other process that were waiting for it can now gain control of it

But what is that resource that the semaphore needs to protect?

Page 14: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Shared Memory

Shared resource that can be accessed like a string (array of characters)

Does not make the actual file, but only the string themselves This is stored in a shared memory (hence, the name)

Page 15: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Initializing Shared Memory

int shmid;

int key = A_LARGE_CONSTANT; // ex. 1234

int size = ANOTHER_CONSTANT; //preferably a power of 2

shmid = shmget(key, size, IPC_CREAT | 0666);

1 key = 1 shared memory segment

size = size of segment to be read

Will return -1 on error.

Page 16: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Using Same Keys

Just like semaphores, you can use same key for a different program This way, calling shmget() will return the same memory segment But there is also that same risk that the key is used by another unrelated program

(especially true when running a central server), which is the same as your semaphores

Page 17: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Accessing Shared Memory

#include <string.h> // for strcpy

char *sharedMem;

char *buffer;

buffer is character array with fixed size

sharedMem = shmat(shmid, NULL, 0);

Will return -1 on error.

Use if((int) sharedMem == -1) to check if shared memory is not allocated

Page 18: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Reading/Writing to Shared Memory

Writing to memory using strcpy (char *destination, char *source);

strcpy(sharedMem, buffer);

Writing from memory using strcpy (char *destination, char *source);

strcpy(buffer, sharedMem);

Note: Data written in shared memory or the buffer to be read is ASSUMED to end in ‘\0’ because otherwise, there will be a segmentation fault

Page 19: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Inter-Process Communication

When semaphores and shared memory is used, there is inter-process communication

Works like pipes, except that they take turns in writing and reading to shared memory

Summary: Initialize shared resources (semaphore and shared memory) Gain control of semaphore Access shared memory Release semaphore

Page 20: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Illustration (Application)

Using the toilet when taking a dump

Going to the barber shop

And many more… these are just some real-life illustrations of semaphores and shared memory

Page 21: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Lab 10: producer.c and consumer.c

Create two c programs, named producer.c and consumer.c, that does the following:

producer.c will be run on the command line using a key provided by the user. The other program, consumer.c, will run also, using this key.

NOTE: Key is supposed to be unique. To check if a semaphore key is already taken, use the ipcs command.

The command ipcs displays all the semaphore keys that are currently in use by shared memory, semaphores, and message queues. Use this for your consumer and producer programs

The producer.c program will be invoked as follows:./producer key filename

Page 22: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Lab 10: producer.c and consumer.c

The key will represent the key to be used for writing in the shared memory, while the filename is the name of the file that is to be written to shared memory

The writing to shared memory will only happen on a per block basis (1 block = 4096 bytes)

Accessing the producer and consumer must be synchronized using a semaphore set (so there should be a semaphore set included!)

This is to ensure that the producer will only write data to shared memory if consumer consumes data (like for example, if a block is already consumed, only will the producer produce)

Use semget() to create a new semaphore in the semaphore set

Page 23: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Lab 10: producer.c and consumer.c

The shared memory must be organized as follows:char data[4096];int size; //size written to shared memory

Producer allocates the shared memory using the system call shmget() This returns an int address location, which will be used for using shmat()

The shared memory can be written to or read from after its address is obtained using shmat()

When both producer and consumer are done with processing the file, shared memory should be deleted using shmdt()

Semaphores should be deleted by the producer after successful processing of the file using shmctl()

Page 24: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Lab 10: producer.c and consumer.c

NOTE: Both semaphore and shared memory SHOULD use the same key value (to maintain consistency)

The same goes for running consumer.c, except it will be the read part of the program NOTE: consumer.c should be able to write results to a file named output.txt

Basically, this is like copying to a file, except with shared memory After copying the file, producer should DELETE THE PREVIOUS FILE to show that it has

been transferred to the consumer side (we are CUTTING the file, not copying it)

Test your program this way (suggestion): Copy your producer.c program to a new folder and consumer.c in another new folder Then copy a file from producer to the folder with consumer.c in it

This is like piping, except that we do it using semaphores

Page 25: CS162B: Semaphores (and Shared Memory) Jacob T. Chan

Lab 10: producer.c and consumer.c

You SHOULD be able to handle errors, like wrong arguments, file opening errors, semaphore errors, etc.

Legal stuff Include a Certificate of Authorship, along with your producer.c and consumer.c programs Filename: CS162B_Lab10_<Section>_<Surname>_<ID Number>.tar Deadline: Next Week Midnight

Tuesday for Section A Thursday for Section B