tags:

views:

77

answers:

2

I am required to create 6 threads to perform a task (increment/decrement a number) concurrently until the integer becomes 0. I am supposed to be using only UNIX commands (Pipelines to be specific) and I can't get my head around how pipelines work, or how I can implement this program.

This integer can be stored in a text file.

I would really appreciate it if anyone can explain how to implement this program

A: 

Pipes are basically simple: input comes in on one end, and is read from the other end. In order to perform basic inter-process communication (IPC), one, original process (the "parent") creates a pipe and then fork()s to make a duplicate of the process (the "child"). At this point the parent and child process each follow separate code paths to do their work. The writing process, usually the child, would write its result to the pipe when done.

If the parent also needs to talk to the child (likely in this case), two pipes must be created and each process will have to wait at some points to receive the other's messages.

Writing code with fork() and pipe() is fairly non-obvious: the linux manpage (http://linux.die.net/man/2/pipe), however, has a nice, simple example of how to make a pipe at the bottom. As far as actual communication is concerned, writing to pipes is typically done with write(), and reading with read() (although other calls, like select() may be useful depending on your needs; as always, read the manpage for more info).

If you don't get what's happening at all, a more in-depth tutorial might be helpful: http://beej.us/guide/bgipc/output/html/multipage/index.html (look at fork and pipe)

A hint for the program: it may help to have one "special" master process which controls all of the synchronization issues.

Frederic Koehler
+1  A: 

The book is right, pipes can be used to protect critical sections, although how to do so is non-obvous.

int *make_pipe_semaphore(int initial_count)
{
   int *ptr = malloc(2 * sizeof(int));
   if (pipe(ptr)) {
       free(ptr);
       return NULL;
   }
   while (initial_count--) 
       pipe_release(ptr);
   return ptr;
}

void free_pipe_semaphore(int *sem)
{
    close(sem[0]);
    close(sem[1]);
    free(sem);
}

void pipe_wait(int *sem)
{
    char x;
    read(sem[0], &x, 1);
}

void pipe_release(int *sem)
{
   char x;
    write(sem[1], &x, 1);
}

The maximum free resources in the semaphore varies from OS to OS but is usually at least 4096. This doesn't matter for protecting a critical section where the initial and maximum values are both 1.

Usage:

/* Initialization section */
int *sem = make_pipe_semaphore(1);



/* critical worker */
{
    pipe_wait(sem);
    /* do work */

    /* end critical section */
    pipe_release(sem);
}
Joshua