两个C文件之间的斐波那契共享内存进程

时间:2018-10-10 20:29:26

标签: c shared-memory fibonacci

你好,我在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;
}

2 个答案:

答案 0 :(得分:0)

共享记忆有两种选择:

数据池-数据池是内核根据请求向进程提供的分配位置。然后其他进程使用用于创建数据池的名称连接到该数据池并从中读取/写入。

管道-管道是另一种共享资源的形式,内核再次根据请求提供资源。区别在于,流水线通常是单向的,而所有过程都可以读写数据池。而且,从管道中进行的读取具有破坏性。

文件-您也可以使用最基本的文件,并且您可能对此很熟悉。

这些是基本解释,您必须研究这些主题才能完全理解和使用它们。同样,每个操作系统都有使用这些概念的特定方式,但是它们都以自己的方式提供。

答案 1 :(得分:0)

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

在当前目录中创建文件fibonacci,该文件将用于对ftok()的调用。

父级派生子进程时,它将调用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;
}