首页 > 解决方案 > 两个c文件之间的斐波那契共享内存进程

问题描述

您好,我在 c 中有一个文件,它从父级到子级共享内存,但我需要将我的代码分成两个单独的文件,同时仍然共享内存。我需要父级创建共享内存并获取 fib 编号的输入。然后子进程打开共享内存对象读取值n,并用fib(n)的值覆盖n值。并显示 fib 系列。这就是我现在所拥有的

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

标签: cshared-memoryfibonacci

解决方案


不要在父进程中附加共享内存,然后在客户端继承它,而是使用ftok()来获取两个进程都使用的公共共享内存密钥。

在当前目录中创建一个文件fibonacci,这将用于调用ftok().

当父进程fork子进程时,它调用execl()来执行子程序,而不是直接包含子代码。子程序不需要任何fork()代码,它只需要附加到相同的共享内存段并填写结果。

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

推荐阅读