Ameya
Ameya

Reputation: 549

Sharing data between threads in C

I have the following main.c:

#include <unistd.h> //has thread calls for fork()
#include <stdio.h>

struct globalInfo{
    int x;
};

int do this()
{
    info.x++;
    printf("%d\n",info.x);
    return 0;
}
int main{
    struct globalInfo info = { .x = 2};
    for(int i = 0 ; i < 5 ; i++)
    {
         if(fork() = 0)
         {
             dothis();
         }
    }
 }

This isn't my exact code, but my question is more easily demonstrated here.

Now the output for the above function is:

3
3
3
3
3

What I want is:

3
4
5
6
7

How do share this struct between threads? It seems like every thread is just creating its own copy of the struct and manipulating its own copy. I've tried to pass a pointer to the info struct as a parameter to dothis(), but that doesn't fix it either. I've also tried placing the info initialization out of the main; that didn't work either..

Help would be greatly appreciated.

Upvotes: 1

Views: 4886

Answers (3)

gkiko
gkiko

Reputation: 2289

As people have already noted you are creating processes not threads. Sharing data among processes is harder. Every process has its own memory address space which means that they may share same code, but their data is private.

There are several techniques if you want to have shared data among processes. One of them is shared memory with memory map

#include <unistd.h> //has thread calls for fork()
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

struct globalInfo{
    int x;
};

char *shm = "/asd8"; // change this before every run to avoid error 22

int dothis()
{
    // sleep(1); // helps to simulate race condition
    int len = sizeof(struct globalInfo);

    int fd = shm_open(shm, O_RDWR, 0);
    void *addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED){
        perror(""); // error handling
    }

    struct globalInfo *info = (struct globalInfo *)addr;
    info->x++;
    printf("%d %d\n", info->x, getpid());

    return 0;
}

int main(){
    struct globalInfo info = { .x = 2};
    int len = sizeof(struct globalInfo);

    int fd = shm_open(shm, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    if (fd == -1)
        perror(""); // error handling

    if(ftruncate(fd, len) == -1){
        printf("%d\n", errno); // osx produces error 22 don't know why
        perror("");
    }
    void *addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    memcpy(addr, &info, len);

    for(int i = 0 ; i < 5 ; i++)
    {
         if(fork() == 0)
         {
             dothis();
             break;
         }
    }
 }

sample output

3 30588
4 30589
6 30590
6 30591
7 30592

Also it would be great if you read chapters from The Linux Programming Interface: A Linux and UNIX System Programming Handbook

  • 24 Process Creation
  • 49 Memory Mapping
  • 53 POSIX Semaphores (you have to solve synchronisation problem after the data is shared)
  • 54 POSIX Shared Memory

Upvotes: 0

bikram990
bikram990

Reputation: 1115

Use any IPC to share data b/w processes. In threads the data can be shared by following methods:

  • return value of thread passed to pthread_exit and catch in pthread_join
  • shared/global resource of process accessed by synchronizing methods

Upvotes: 0

asio_guy
asio_guy

Reputation: 3767

fork() doesnot create a thread it creates processes, processess will have different address spaces altogether hence data wil not be shared even if it is global data.

in case you are thinking of threads use pthreads incase you are looking for processes you need to use IPC mechanisms

Upvotes: 2

Related Questions