S60 Open C
Threads, Processes, IPC, and Synchronization

Threads, Processes, IPC, and Synchronization

Table of Contents

How to communicate between two threads or processes
Pipes
Named pipes (mkfifo)
Message queues
Shared memory

 


How to communicate between two threads or processes

In order to communicate between two threads within a process and also between unrelated processes, use the following mechanisms:

  • Pipes
  • Named pipes
  • Message queues
  • Shared memory

NOTE! It is fully possible to use all these mechanisms from a Symbian application and communicate with a thread or process created using thread or process creation functions provided by Open C.

 


Pipes

Pipes can be used when a process creates child processes or threads and wants to communicate with them. The following steps are needed:

  • Declare a global variable with array [2] of data type int.
  • Create a pipe.
  • Create a thread.
  • Read data from the pipe from the parent thread.
  • Write data from the child thread.
  • Close the read or write descriptor

Example:

#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

int pipefd[2];
unsigned int threadid;

// thread entry point
void* PipeWriterThread(void* arg)
{
   char ch[32];
   strcpy(ch, "abcd");
   write(pipefd[1], ch, 4);
   return NULL;
}

void CreateThreadL()
{
   pthread_create(&threadid,(pthread_attr_t *)NULL,PipeWriterThread, NULL);
}

int main()
{
   if(0 == pipe(pipefd))
   {
       char ch[128];
       CreateThreadL();
       read(pipefd[0], ch, 10);
       close(pipefd[1]);
       close(pipefd[0]);
   }
   return 0;
}

 


Named pipes (mkfifo)

Named pipes are used to communicate between threads within a process or between two unrelated processes. The following pattern is used:

  • Create a named pipe using mkfifo.
  • Create a process or thread and open this pipe in write mode.
  • Another process or thread can open the same in read mode.
  • Close the read or write descriptor.

Example:

#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>

const char* fifopath = "C:\\mkfifo.file";
unsigned int threadid;

// thread entry point
void* FifoWriterThread(void* arg)
{
   const char* buf = "somejunk";
   TInt fd = open (fifopath, O_WRONLY);
   if(fd > 0 )
   {
      write(fd, buf, 9);     
      close(fd);
   }
   return 0;
}

void CreateThreadL()
{
   pthread_create(&threadid,(pthread_attr_t *)NULL,FifoWriterThread, NULL);
}

void OpenForRead()
{
   int err = mkfifo (fifopath, 0666);
   if(err != 0)
   {
       // probably file already exists, delete the file
       unlink(fifopath); 
       // try once more..
       err = mkfifo (fifopath, 0666);
       if(err != 0)
       {
            return;
       }
   }
   CreateThreadL();
   char buf[128];
   TInt fd = open (fifopath, O_RDONLY);
   if ( fd ( 0 )
       {
           return ;
       }
   err = read (fd, buf, 128);  
   close(fd);   
   unlink(fifopath);
}    

int main()
{
   OpenForRead();
   return 0;
}

 


Message queues

Message queues are used to communicate between threads within a process or two unrelated processes. The following pattern is used:

  • Create a message queue using msgget.
  • Create a process or thread and send some message to this message queue.
  • Read the message from the main thread.
  • Delete the message queue.

Example:

#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define MSG_KEY 1000
pthread_t threadid;

void* MsgDSndThread(void* arg)
{
   struct msgbuf *snd = (struct msgbuf*)malloc(16);
   key_t fd;
   snd->mtype = 1;
   strcpy(snd->mtext, "message");
   fd = msgget(MSG_KEY, IPC_CREAT);
   msgsnd(fd, snd, 12, 0);
   free(snd);
   return 0;
}

void CreateThreadL()
   {
   pthread_create(&threadid,(pthread_attr_t *)NULL,MsgDSndThread, NULL);
   }

int main()
{
   struct msgbuf *rcv = (struct msgbuf*)malloc(16);
   key_t fd = msgget(MSG_KEY, IPC_CREAT);
   CreateThreadL();
   msgrcv(fd, rcv, 6, 0, 0);
   msgctl(fd, IPC_RMID, NULL);
   free(rcv);
   return 0;
}

 


Shared memory

Shared memory is used to communicate between threads within a process or two unrelated processes. The following pattern can be used:

  • Create a shared memory segment using shmget.
  • Create one process or thread and send some message to this message queue.
  • Read the message from the main thread.
  • Delete the message queue.

Example:

#include <sys/shm.h>
#include <string.h>
#include <pthread.h>

pthread_t threadid;
#define SHM_KEY 1000

void* ShmReadThread(void* arg)
{
   int shmid = shmget(SHM_KEY, 1024, IPC_CREAT);
   char* ch = (char*)shmat(shmid, 0, 0);
   char name[10];
   strncpy(name, ch, 3);
   // name contained "abc"
   shmdt(ch);
   return 0;
}

void CreateThreadL()
   {
   pthread_create(&threadid,(pthread_attr_t *)NULL,ShmReadThread, NULL);
   }

int main()
{
   char* ch;
   int shmid = shmget(SHM_KEY, 1024, IPC_CREAT);
   int threadRetVal = 0;
   if( shmid == -1)
       return -1;
   ch = (char*)shmat(shmid, 0, 0);
   if((int)ch == -1)
   {
       shmctl(shmid, IPC_RMID, NULL);
       return -1;
   }
   strcpy(ch, "abc");
   CreateThreadL();
   
   pthread_join(threadid, (void**)threadRetVal);
   shmdt(ch);
   shmctl(shmid, IPC_RMID, NULL);
   return 0;
}

Give feedback of this section


©Nokia 2007

Back to top


This material, including documentation and any related computer programs, is protected by copyright controlled by Nokia. All rights are reserved. Copying, including reproducing, storing, adapting or translating, any or all of this material requires the prior written consent of Nokia. This material also contains confidential information, which may not be disclosed to others without the prior written consent of Nokia.

Nokia is a registered trademark of Nokia Corporation. S60 and logo is a trademark of Nokia Corporation. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. Other company and product names mentioned herein may be trademarks or tradenames of their respective owners.