fibonacci sequence using shared memory in C

2019-06-08 18:25发布

问题:

I got a question to solve but it is giving me errors:

2009-EE-182-Part2.c: In function ‘main’:
2009-EE-182-Part2.c:35:13: error: expected identifier or ‘(’ before ‘->’ token
2009-EE-182-Part2.c:40:22: error: expected identifier or ‘(’ before ‘->’ token
2009-EE-182-Part2.c:41:14: error: expected identifier or ‘(’ before ‘->’ token
2009-EE-182-Part2.c:42:22: error: expected expression before ‘shared_data’
2009-EE-182-Part2.c:44:15: error: expected identifier or ‘(’ before ‘->’ token
2009-EE-182-Part2.c:54:15: error: expected expression before ‘shared_data’
2009-EE-182-Part2.c:55:19: error: expected expression before ‘shared_data’

The code is:

# include <stdio.h>
# include <sys/shm.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
# define MAX_SEQUENCE 10

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

char* shared_memory; /* a pointer to the shared memory segment */

int main()
{
int a,b,m,n,i,j;
a=0; b=1;
printf("Enter the number of a Fibonacci Sequence:\n");
scanf("%d", &m);

if (m < 0)
        printf("Please enter a non-negative integer\n");
else if (m> MAX_SEQUENCE)
        printf("Please enter an integer less than 10\n");

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

int segment_size = sizeof(shared_data); /* the size (in bytes) of the shared memory segment */
segment_id = shmget(IPC_PRIVATE, segment_size, S_IRUSR | S_IWUSR); /** allocate  a shared memory segment */
shared_data *shared_memory = shmat(segment_id, NULL, 0); /** attach the shared memory segment */
printf("\nshared memory segment %d attached at address %p\n", segment_id, shared_memory);

shared_data->sequence_size = m;
pid_t pid;
pid = fork();
    if (pid == 0){
        printf("Child is producing the Fibonacci Sequence...\n");
        shared_data->fib_sequence[0] = a;
    shared_data->fib_sequence[1] = b;
        for (i=2;i<shared_data->sequence_size;i++){
        n=a+b;
        shared_data->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_data->sequence_size;i++)
        printf("%ld ", shared_data->fib_sequence[i]);
    }

/**printf("%s \n", shared_memory);  now print out the string from shared memory */

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

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

return 0;
}

The statement is "An approach to designing fibonacci program is to establish a shared-memory segment between the parent and child processes. This technique allows the child to write contents of the Fibonacci sequence to the shared- memory segment and has the parent output the sequence when the child completes. Because the memory is shared, any changes the child makes will be reflected in parent process as well. This program will be structured using POSIX shared memory as described in http://graphics.im.ntu.edu.tw/~robin/courses/os07/code/03proc/shm-posix.c This program first requires creating the data structure for the shared-memory segment. This is most easily accomplished using a struct. This data structure will contain two items: 1. A fixed size array of size MAX_SEQUENCE that will hold the Fibonacci values and 2. The size of the sequence the child process is to generate, i.e. sequence_size, where sequence_size ≤ MAX_SEQUENCE.

These items can be represented in a struct as follows:

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

The parent process will progress through the following steps: a. Accept the parameter passed on the command line and perform error checking to ensure that the parameter is ≤ MAX_SEQUENCE. b. Create a shared memory segment of size shared_data . c. Attach the shared-memory segment to its address space. d. Set the value of sequence_size to the parameter on the command line. e. Fork the child process and invoke the wait() system call to wait for the child process to finish. f. Output the value of Fibonacci sequence in the shared- memory segment. g. Detach and remove the shared-memory segment.

The shared-memory segment will be attached to the child’s address space as well as the parent’s address space. The child process will then write the Fibonacci sequence to the

shared-memory segment. The parent and child processes must be synchronized so that the parent would not output the Fibonacci sequence until the child finishes generating the sequence. NOTE: Display sufficient messages on the console to let the user know when a certain action is performed, e.g. creation and termination of child process, etc."

Expert minds Kindly help.

回答1:

First problem:

int a,b,m,n,i,j;

sequence.fib_sequence[0] = a;
sequence.fib_sequence[1] = b;

You never initialise a and b, thus you get garbage (and undefined behaviour). Initialise

a = 0;
b = 1;

Deeper problem: You set up a shared memory segment, but never use it. You use the global

shared_data sequence;

to write to in the child, and to read from in the parent. Since that global has nothing to do with the shared memory you set up, the child's actions don't modify the parent's sequence.

You should use shared_memory, the pointer to the shared memory to write to and read from. So instead of a char*, it should be

shared_data *shared_memory = shmat(...);

and then use shared_memory->sequence[i] etc.

After fixing the shared_data/shared_memory mixup and adding a bit of error-checking, the programme could look like

# 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;
}