PDA

View Full Version : need help c++ semaphores



realitybites
November 12th, 2007, 05:01 PM
i have writer and reader processes (two instances of writer process)
i want to use semaphores, with down and up operations

i have no problem implementing semaphores or creating processes but,
my problem using interprocess communication. how can i use the shared resource (an array for example) between processes? how can i make them use the same array?

i also guess i need to use another semaphore to lock and unlock the array?

here are my processes:


pid0= fork();
if(pid0==0){
execl("writer", (char *)0);
}

pid1= fork();
if(pid1==0){
execl("reader", (char *)0);
}

pid2= fork();
if(pid2==0){
execl("reader", (char *)0);
}

any useful link or suggestion is appreciated. i found many detailed info about thread synchronization but i need to use processes.

bunker
November 12th, 2007, 06:08 PM
You can use pretty much all the same techniques with threads and processes, however if you're doing an exec call the exec'd command (here 'reader' and 'writer') won't be able to have access to the calling process. Instead, they need to be part of your program, eg:


if (!fork()) {
reader();
}

You can see that's almost the same as launching a thread anyway.

If you have to use a separate command, you would need to redirect stdin/stdout and use pipe() for communication, or possibly think something up using other modes of IPC like sockets and named pipes.

realitybites
November 12th, 2007, 07:33 PM
i have to use seperate processes.
i will give those a try, i have read about pipe but i wasn't so sure if i can use that

slavik
November 12th, 2007, 07:36 PM
use pipes for interprocess communication and global buffer for threads.

aks44
November 12th, 2007, 08:43 PM
use [...] global buffer for threads.

Better use message queues, they are sooo easy to manage... :)

realitybites
November 12th, 2007, 09:51 PM
i piped the stdin and stdout. but since the stdout of one process is connected to the other process' stdin, i can't print messages from that process, which i need to do

but i think there should be a solution, which i don't know:)

this is an assignment by the way. that's why i'm saying "i should" or "i have to"

slavik
November 12th, 2007, 11:48 PM
Better use message queues, they are sooo easy to manage... :)
Are they? (have never seen the code)

I find that lock, read/write, unlock is pretty simple, too. But I don't do much parallel programming atm.

the_unforgiven
November 13th, 2007, 06:45 AM
i have writer and reader processes (two instances of writer process)
i want to use semaphores, with down and up operations

i have no problem implementing semaphores or creating processes but,
my problem using interprocess communication. how can i use the shared resource (an array for example) between processes? how can i make them use the same array?

i also guess i need to use another semaphore to lock and unlock the array?

here are my processes:


pid0= fork();
if(pid0==0){
execl("writer", (char *)0);
}

pid1= fork();
if(pid1==0){
execl("reader", (char *)0);
}

pid2= fork();
if(pid2==0){
execl("reader", (char *)0);
}

any useful link or suggestion is appreciated. i found many detailed info about thread synchronization but i need to use processes.
If you need to use a data structure across processes (not threads), then shared memory (http://en.wikipedia.org/wiki/Shared_memory) is the way to go.
It's a standard POSIX IPC mechanism.

And yes, to serialize the access to the shared data structures, you would need some sort of lock/mutex (either with a semaphore or some other mechanism) to protect the data structure.

realitybites
November 13th, 2007, 01:19 PM
do you know any useful tutorial about shared memory?
i found this: shmdemo.c (http://www.ecst.csuchico.edu/~beej/guide/ipc/shmdemo.c)
but i didn't understand how to make processes communicate and couldn't find a way to use it with an array.
this is my first experience with IPC :)

aks44
November 13th, 2007, 08:06 PM
Better use message queues, they are sooo easy to manage...Are they? (have never seen the code)

I find that lock, read/write, unlock is pretty simple, too. But I don't do much parallel programming atm.


Locking individual variables is OK for small scale projects IMHO. But you can hardly sustain fine-grained locking when your project grows (number of variables and number of threads).


Even the famous guru Herb Sutter warns about locks (emphasis mine):

- Locks are not composable. You canít take two pieces of code that use locks, each of them provably correct, and put them together and get something new thatís sure to be correct. You canít test for that. And itís common now for two pieces of software to be composed for the first time on the userís machine.
- Locks are hard for experts to get right.


So you're basically left with coarse-grained locking (which denies the whole point of concurrent programming), or with endless hours of hair-pulling. The only other practical option I know of are indeed message queues.


Each queue (a double-linked list is probably the best choice to implement it) has its own mutex controlling pushes/pops, and each thread has just *one* input message queue (several threads can share a single queue though). On Windows I also use a helper event (not sure if events exist on Linux though) to wake up the slave thread as soon as possible without constantly polling the queue. A message should be self-contained as much as possible, ie. a thread should be able to work exclusively on the message it is currently processing, without need to acquire any lock on external data.


Depending on your requirements it may (often will not) involve some copying overhead, but the benefits WRT enhanced concurrency generally beat the cost of that overhead.

Of course as any concurrent programming it needs to be designed very carefully, but in my experience it alleviates many problems related to fine-grained locking (ever rewrote some code from scratch because you just couldn't determine where the dead/livelock comes from?) and it really increases concurrency compared to coarse-grained models. The real good part is that the message-queue model is totally asynchronous so the "non-composability" evoked by Sutter disappears.


To sum it up: the design can hardly be more simple, it has almost zero risk and many benefits. Win-win... :)

slavik
November 14th, 2007, 01:22 AM
Each queue (a double-linked list is probably the best choice to implement it) has its own mutex controlling pushes/pops, and each thread has just *one* input message queue (several threads can share a single queue though). On Windows I also use a helper event (not sure if events exist on Linux though) to wake up the slave thread as soon as possible without constantly polling the queue. A message should be self-contained as much as possible, ie. a thread should be able to work exclusively on the message it is currently processing, without need to acquire any lock on external data.

What you can do is sleep until a variable has changed (I forgot what this is called).