gpt4 book ai didi

C:共享内存和 fork ,多次执行打印语句

转载 作者:太空宇宙 更新时间:2023-11-04 01:45:06 26 4
gpt4 key购买 nike

我正在开发一个程序,该程序使用共享内存计算给定数字的 collat​​z 猜想。父进程将创建一个子进程,然后子进程将计算猜想,并使用共享内存将其提供给父进程,以便父进程打印出该值。如果子进程无法计算出完整的猜想,因为它用完了共享内存结构中存储它的空间,那么父进程将创建一个新的子进程从上一个停止的地方继续。我遇到了一个问题,父进程中显示子进程共享内存结果的打印语句被多次打印。

/*********************************
* Applies the Collatz conjecture
* to the given positive integer
* using shared memory.
*********************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/stat.h>

#define MAX_SEQUENCE 30

typedef struct {
int size; // Number of values in this sequence
short partial; // Flag
long num[MAX_SEQUENCE];
} shared_data;

int main(int argc, char* argv[])
{
// Name of the shared memory segment
const char *name = "myMemorySeg";

// Shared memory file descriptor
int shm_fd;

// A pointer to the shared memory segment
shared_data* shared_memory;

// Handle input validation
if (argc != 2) {
fprintf(stderr, "Usage: %s num\n", argv[0]);
exit(1);
}
// Get number from argument
int n = atoi(argv[1]);

do {
int pid;
// Create a child process with shared memory space
pid = create_child(&name, &shm_fd, &shared_memory);

// Parent
if (pid > 0) {
wait(NULL);

// Print out collatz results
int i;
for (i = 0; i < shared_memory->size; i++)
printf("%d ", shared_memory->num[i]);

// If this was only part of the sequence
// Then start the next sequence at the collatz of the last sequence value
if (shared_memory->partial)
n = get_collatz(shared_memory->num[MAX_SEQUENCE - 1]);
}
// Child
else if (pid == 0) {
// Generate the collatz sequence and store the result in the shared memory
int i = 0;
shared_memory->num[i++] = n; // Store the initial number
while (n != 1 && i < MAX_SEQUENCE) {
n = get_collatz(n);
shared_memory->num[i++] = n; // Store the next number
}
// If we have filled the sequence array and n hasn't reached 1
// then this is only a partial sequence
shared_memory->partial = (i == MAX_SEQUENCE && n != 1) ? 1 : 0;
// What is the sequence size?
shared_memory->size = i;

// Kill the child process
exit(0);
}

// Remove the shared memory object
shm_unlink(name);

} while (shared_memory->partial); // While the last sequence was partial
printf("\n");

return 0;
}

/********************************
* create_child()
*
* Opens a shared memory space
* and creates a child process
* to share that space with the
* parent.
*
* Returns the process id if
* successful, otherwise exits
* the parent process.
********************************/
int create_child(char **name, int *shm_fd, shared_data** shared_memory) {
// Create a shared memory object
*shm_fd = shm_open(*name, O_CREAT|O_RDWR, 0666);

// Configure the size of the shared memory object
ftruncate(*shm_fd, sizeof(shared_data));

// Memory map the shared memory object
*shared_memory = (shared_data *) mmap(0, sizeof(shared_data), PROT_WRITE, MAP_SHARED, *shm_fd, 0);

// Create child process
int pid;
// Return -1 if error
if ((pid=fork()) == -1) {
perror("Failed to create child process");
exit(1); // Kill parent process
}
// Otherwise return the pid created by fork
return pid;
}

/********************************
* get_collatz()
*
* Returns the result of running
* the input n through the
* collatz conjecture function.
********************************/
int get_collatz(int n) {
return (!(n%2)) ? (n/2) : (3*n + 1);
}

这是控制台输出的样子:

Console output

有趣的是,如果我在父进程从共享内存中打印出子进程的结果之前向父进程添加一个带有新行的打印语句,如下所示:

    do {
int pid;
printf("\n");
// Create a child process with shared memory space
pid = create_child(&name, &shm_fd, &shared_memory);

// Parent
if (pid > 0) {
wait(NULL);

// Print out collatz results
int i;
for (i = 0; i < shared_memory->size; i++)
printf("%d ", shared_memory->num[i]);

// If this was only part of the sequence
// Then start the next sequence at the collatz of the last sequence value
if (shared_memory->partial)
n = get_collatz(shared_memory->num[MAX_SEQUENCE - 1]);
}
// Child

然后打印语句将输出正确的次数。

Console output with print statement

另一个有趣的事实是,这个解决方案只有在我将换行打印语句放在 create_child() 调用之前才有效,如果我将它放在之后则无效。

我不希望它们被换行分隔,我希望它们全部打印在一行上。知道是什么导致了这些额外的打印语句吗?

最佳答案

您要么需要添加适当的刷新调用,要么需要将标准输出更改为不被缓冲。

图书馆正努力提高效率,直到它有一个完整的行才真正写入终端。因此它将部分行存储在缓冲区中。当您fork 时,您会得到两个基本相同的进程,也就是说,它们每个都具有相同的缓冲数据。如果他们都完成一行输出,他们都将写入缓冲数据。

您可能仍然有一个问题,即所有不同的输出都混杂在一起。更常用的处理方法是只让一个进程负责所有输出,“工作”进程将它们的结果传回给“管理器”进程,以一种理智、有序的方式打印出来。

关于C:共享内存和 fork ,多次执行打印语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55189716/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com