c - 两个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;
}
解决方案
不要在父进程中附加共享内存,然后在客户端继承它,而是使用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;
}
推荐阅读
- javascript - Angular 8 facebook登录并将数据保存到本地存储中
- firebase - 必须向 Text 小部件颤振提供非空字符串
- python - 如果没有监视器插入 PI,psutil 将无法运行
- javascript - 反应上下文给出了未定义的对象
- javascript - 我在使用 Firebase 身份验证时遇到问题
- reactjs - 对象作为 React 子对象无效(找到:带有键 {username} 的对象)。如果您打算渲染一组孩子,请改用数组
- reactjs - 在 typescript-redux 中使用 thunk 的动作创建者,将动作视为未定义
- python - 更新整个用户群的均值和标准差
- windows-subsystem-for-linux - WSL 停止工作并出现错误:0x80070003
- geth - geth 进程已停止,因为 debug_traceBlockByNumber