0

Hello I have a single file in c that shares memory from the parent to child but I need my code separated into two separate files while still sharing the memory. I need the parent to create the shared memory and get the input of the fib number. Then the child process opens the share memory object to read the value n and overwrite the value n by the value of fib(n). and displays the fib series. This is what I have now

#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>

// So we could use other sizes without editing the source.
#ifndef MAX_SEQUENCE
# define MAX_SEQUENCE 10
#endif

// Check that MAX_SEQUENCE is large enough!
#if MAX_SEQUENCE < 2
#error MAX_SEQUENCE must be at least 2
#endif

typedef struct{
    long fib_sequence[MAX_SEQUENCE];
    int sequence_size;
} shared_data;

int main()
{
    int a, b, m, n, i;
    a = 0; b = 1;

    printf("Enter the number of a Fibonacci Sequence:\n");
    // Always check whether input conversion worked
    if (scanf("%d", &m) != 1) {
        printf("Invalid input, couldn't be converted.\n");
        return EXIT_FAILURE;
    }

    if (m <= 0) {
        printf("Please enter a positive integer\n");
        return EXIT_FAILURE; // exit if input is invalid
    } else if (m > MAX_SEQUENCE) {
        printf("Please enter an integer less than %d\n", MAX_SEQUENCE);
        return EXIT_FAILURE; // exit if input is invalid
    }

    /* the identifier for the shared memory segment */
    int segment_id;

    /* the size (in bytes) of the shared memory segment */
    size_t segment_size = sizeof(shared_data);

    /* allocate a shared memory segment */
    segment_id = shmget(IPC_PRIVATE, segment_size, S_IRUSR | S_IWUSR);

    // Check result of shmget
    if (segment_id == -1) {
        perror("shmget failed");
        return EXIT_FAILURE;
    }

    /* attach the shared memory segment */
    shared_data *shared_memory = shmat(segment_id, NULL, 0);

    // Check whether attaching succeeded
    if ((void*)shared_memory == (void*)-1) {
        perror("shmat failed");
        goto destroy; // clean up
    }
    printf("\nshared memory segment %d attached at address %p\n", segment_id, (void*)shared_memory);

    shared_memory->sequence_size = m;
    pid_t pid;
    pid = fork();
    if (pid == 0){
        printf("Child is producing the Fibonacci Sequence...\n");
        shared_memory->fib_sequence[0] = a;
        shared_memory->fib_sequence[1] = b;
        for (i = 2; i < shared_memory->sequence_size; i++){
            n = a+b;
            shared_memory->fib_sequence[i] = n;
            a = b;
            b = n;
        }
        printf("\nChild ends\n");
    }
    else{
        printf("Parent is waiting for child to complete...\n");
        wait(NULL);
        printf("Parent ends\n");
        for(i = 0; i < shared_memory->sequence_size; i++) {
            printf("%ld ", shared_memory->fib_sequence[i]);
        }
        printf("\n");
    }

    /* now detach the shared memory segment */
    if (shmdt(shared_memory) == -1) {
        fprintf(stderr, "Unable to detach\n");
    }

destroy:
    /* now remove the shared memory segment */
    shmctl(segment_id, IPC_RMID, NULL);

    return 0;
}
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thats a very nice looking spaghetti you have there. – Swordfish Oct 10 '18 at 20:30
  • There is no question in the question. – Eugene Sh. Oct 10 '18 at 20:33
  • So you are asking how to create and use shared memory in an unknown operating system? – Michael Dorgan Oct 10 '18 at 20:36
  • I want to know how to have shared memory in a linux system between two c files to complete the program described above. – Alex Gordo Oct 10 '18 at 20:37
  • @AlexGordo When you say two C files, do you mean two separate executables (with each C file having its own `main`) or do you mean two files linked together into a single executable? – dbush Oct 10 '18 at 20:44
  • @EugeneSh. Thats why there is no answer in the answers. – Swordfish Oct 10 '18 at 20:45
  • @dbush two separate processes, a child and a parent each in their own c file – Alex Gordo Oct 10 '18 at 20:53
  • @AlexGordo That doesn't answer the question. Will each C file have its own `main` function (meaning you'll need to `fork` **and** `exec`), or will they have the same `main` with one file having the parent-specific functions and one file having the child-specific functions? – dbush Oct 10 '18 at 20:55
  • https://stackoverflow.com/questions/13762397/fibonacci-sequence-using-shared-memory-in-c?rq=1 ?? – Michael Dorgan Oct 10 '18 at 20:57
  • @dbush they both have a main() – Alex Gordo Oct 10 '18 at 20:59
  • @Michael Dorgan I saw that question it isn't really close to what I'm asking – Alex Gordo Oct 10 '18 at 21:00
  • Use a shared key instead of `IPC_PRIVATE` so that both processes can get the same shared memory. You can use `ftok()` to generate a unique key from a pathname. Other than that, the code is mostly the same. – Barmar Oct 10 '18 at 21:51
  • @barmar can you show me what that would look like in two separate files, I'm so lost. This is my first post and I need help. – Alex Gordo Oct 10 '18 at 21:55
  • What part don't you understand? Why does it matter if this is your first post? – Barmar Oct 10 '18 at 21:57
  • @barmar I don't know what part of the code goes into each file to communicate correctly – Alex Gordo Oct 10 '18 at 21:58

2 Answers2

0

There are a couple of options for shared memories :

Datapools - Datapool is an allocated location that kernel provides to a process upon request. Then other processes use the name which was used to create the data pool to connect to it and read/write from it.

Pipelines - Pipeline is another form of sharing resources which again kernel provides upon request. The difference is pipeline is usually one-way whereas data pool can be read and written by all the processes. Also, reads from the pipeline are destructive.

Files - You can also use files which is the most basic and you are probably familiar with it.

These are basic explanations, you have to research on these topics to fully understand and use them. Also, each operating system has a specific way of using these concepts, but all of them provide it (in their own way).

TheEngineer
  • 792
  • 6
  • 18
0

Instead of attaching the shared memory in the parent and then inheriting it in the client, use ftok() to get a common shared memory key that's used by both processes.

Create a file fibonacci in your current directory, this will be used in the calls to ftok().

When the parent forks the child process, it calls execl() to execute the child program, rather than including the child code directly. The child program doesn't need any of the fork() code, it just needs to attach to the same shared memory segment and fill in the results.

fibonacci.h

#ifndef FIBONACCI_H
#define FIBONACCI_H

// So we could use other sizes without editing the source.
#ifndef MAX_SEQUENCE
# define MAX_SEQUENCE 10
#endif

// Check that MAX_SEQUENCE is large enough!
#if MAX_SEQUENCE < 2
#error MAX_SEQUENCE must be at least 2
#endif

#define TOKEN_PATH "fibonacci"

typedef struct{
    long fib_sequence[MAX_SEQUENCE];
    int sequence_size;
} shared_data;

#endif

testparent.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>

#include "fibonacci.h"

int main()
{
    int m, i;
    printf("Enter the number of a Fibonacci Sequence:\n");
    // Always check whether input conversion worked
    if (scanf("%d", &m) != 1) {
        printf("Invalid input, couldn't be converted.\n");
        return EXIT_FAILURE;
    }

    if (m <= 0) {
        printf("Please enter a positive integer\n");
        return EXIT_FAILURE; // exit if input is invalid
    } else if (m > MAX_SEQUENCE) {
        printf("Please enter an integer less than %d\n", MAX_SEQUENCE);
        return EXIT_FAILURE; // exit if input is invalid
    }

    /* the identifier for the shared memory segment */
    int segment_id;

    /* the size (in bytes) of the shared memory segment */
    size_t segment_size = sizeof(shared_data);

    /* Get shared memory token */
    key_t token = ftok(TOKEN_PATH, 0);
    if (token == -1) {
        perror("ftok");
        return EXIT_FAILURE;
    }

    /* allocate a shared memory segment */
    segment_id = shmget(token, segment_size, S_IRUSR | S_IWUSR | IPC_CREAT);

    // Check result of shmget
    if (segment_id == -1) {
        perror("shmget failed");
        return EXIT_FAILURE;
    }

    /* attach the shared memory segment */
    shared_data *shared_memory = shmat(segment_id, NULL, 0);

    // Check whether attaching succeeded
    if ((void*)shared_memory == (void*)-1) {
        perror("shmat failed");
        goto destroy; // clean up
    }
    printf("\nshared memory segment %d attached at address %p\n", segment_id, (void*)shared_memory);

    shared_memory->sequence_size = m;
    pid_t pid;
    pid = fork();
    if (pid == 0){
        execl("./testchild", "./testchild", (char *)NULL);
        perror("execl"); // If it returns it must have failed
        return EXIT_FAILURE;
    }
    else{
        printf("Parent is waiting for child to complete...\n");
        wait(NULL);
        printf("Parent ends\n");
        for(i = 0; i < shared_memory->sequence_size; i++) {
            printf("%ld ", shared_memory->fib_sequence[i]);
        }
        printf("\n");
    }

    /* now detach the shared memory segment */
    if (shmdt(shared_memory) == -1) {
        fprintf(stderr, "Unable to detach\n");
    }

destroy:
    /* now remove the shared memory segment */
    shmctl(segment_id, IPC_RMID, NULL);

    return 0;
}

testchild.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>

#include "fibonacci.h"

int main()
{
    int a, b, n, i;
    a = 0; b = 1;

    /* the identifier for the shared memory segment */
    int segment_id;

    /* the size (in bytes) of the shared memory segment */
    size_t segment_size = sizeof(shared_data);

    /* Get shared memory token */
    key_t token = ftok(TOKEN_PATH, 0);
    if (token == -1) {
        perror("ftok");
        return EXIT_FAILURE;
    }

    /* allocate a shared memory segment */
    segment_id = shmget(token, segment_size, S_IRUSR | S_IWUSR);

    // Check result of shmget
    if (segment_id == -1) {
        perror("shmget failed");
        return EXIT_FAILURE;
    }

    /* attach the shared memory segment */
    shared_data *shared_memory = shmat(segment_id, NULL, 0);

    // Check whether attaching succeeded
    if ((void*)shared_memory == (void*)-1) {
        perror("shmat failed");
        return EXIT_FAILURE;
    }
    printf("\nshared memory segment %d attached at address %p\n", segment_id, (void*)shared_memory);

    printf("Child is producing the Fibonacci Sequence...\n");
    shared_memory->fib_sequence[0] = a;
    shared_memory->fib_sequence[1] = b;
    for (i = 2; i < shared_memory->sequence_size; i++){
        n = a+b;
        shared_memory->fib_sequence[i] = n;
        a = b;
        b = n;
    }
    printf("\nChild ends\n");

    /* now detach the shared memory segment */
    if (shmdt(shared_memory) == -1) {
        fprintf(stderr, "Unable to detach\n");
    }

    return 0;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612