Я работаю над программой, которая вычисляет гипотезу Коллатца для заданного числа, используя общую память. Родитель создаст дочерний процесс, затем ребенок вычислит гипотезу и, используя разделяемую память, предоставит ее родителю, чтобы родитель мог распечатать значение.
Если дочерний элемент не может вычислить полную гипотезу, поскольку ему не хватает места для хранения ее в структуре разделяемой памяти, тогда родительский процесс создаст новый дочерний процесс, который продолжится там, где остановился последний.
У меня возникла проблема, когда операторы print в родительском процессе, которые отображают результаты дочерних процессов из общей памяти, печатаются несколько раз.
/*********************************
* 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);
}
Вот как выглядит вывод консоли:
Интересно, если я добавлю оператор печати с новой строкой в родительский процесс, прежде чем он выведет результаты дочернего процесса из общей памяти, вот так:
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
Тогда операторы вывода будут выводиться правильное количество раз.
Еще один интересный факт заключается в том, что это решение работает, только если я помещаю оператор печати новой строки перед вызовом create_child (), а не если я помещаю его после.
Я не хочу, чтобы они были разделены новыми строками, я хочу, чтобы они печатали все в одной строке. Любые идеи, что вызывает эти дополнительные заявления печати?