C:共享内存和分叉,打印语句执行多次
我正在开发一个程序,使用共享内存计算给定数字的collatz猜想。父进程将创建一个子进程,然后子进程将计算该猜想,并使用共享内存将其提供给父进程,以便父进程可以打印出该值。 如果子进程无法计算完整的推测,因为它在共享内存结构中的存储空间不足,那么父进程将创建一个新的子进程,在最后一个停止的位置继续。 我遇到一个问题,父进程中显示共享内存中孩子结果的print语句被多次打印C:共享内存和分叉,打印语句执行多次,c,C,我正在开发一个程序,使用共享内存计算给定数字的collatz猜想。父进程将创建一个子进程,然后子进程将计算该猜想,并使用共享内存将其提供给父进程,以便父进程可以打印出该值。 如果子进程无法计算完整的推测,因为它在共享内存结构中的存储空间不足,那么父进程将创建一个新的子进程,在最后一个停止的位置继续。 我遇到一个问题,父进程中显示共享内存中孩子结果的print语句被多次打印 /********************************* * Applies the Collatz conj
/*********************************
* 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);
}
/*********************************
*应用Collatz猜想
*到给定的正整数
*使用共享内存。
*********************************/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义最大\u序列30
类型定义结构{
int size;//此序列中的值数
短部分;//标志
long num[MAX_序列];
}共享数据;
int main(int argc,char*argv[])
{
//共享内存段的名称
const char*name=“myMemorySeg”;
//共享内存文件描述符
int shm_fd;
//指向共享内存段的指针
共享数据*共享内存;
//处理输入验证
如果(argc!=2){
fprintf(stderr,“用法:%s num\n”,argv[0]);
出口(1);
}
//从参数中获取数字
int n=atoi(argv[1]);
做{
int-pid;
//创建具有共享内存空间的子进程
pid=创建子对象(&name,&shm\u fd,&shared\u内存);
//母公司
如果(pid>0){
等待(空);
//打印collatz结果
int i;
对于(i=0;isize;i++)
printf(“%d”,共享内存->num[i]);
//如果这只是序列的一部分
//然后在最后一个序列值的collatz处开始下一个序列
如果(共享内存->部分)
n=get_collatz(共享内存->num[MAX_SEQUENCE-1]);
}
//孩子
否则如果(pid==0){
//生成collatz序列并将结果存储在共享内存中
int i=0;
共享内存->num[i++]=n;//存储初始编号
而(n!=1&&inum[i++]=n;//存储下一个数字
}
//如果我们已经填充了序列数组,而n还没有达到1
//那么这只是一个部分序列
共享内存->部分=(i==MAX\u SEQUENCE&&n!=1)?1:0;
//序列大小是多少?
共享内存->大小=i;
//终止子进程
出口(0);
}
//删除共享内存对象
shm_取消链接(名称);
}while(shared_memory->partial);//当最后一个序列是partial时
printf(“\n”);
返回0;
}
/********************************
*创建子对象()
*
*打开共享内存空间
*并创建一个子进程
*与客户共享该空间
*家长。
*
*如果需要,返回进程id
*成功,否则退出
*父进程。
********************************/
int创建子对象(字符**名称,int*shm\u fd,共享数据**共享内存){
//创建共享内存对象
*shm_fd=shm_open(*名称,O_创建| O_RDWR,0666);
//配置共享内存对象的大小
ftruncate(*shm_fd,sizeof(共享数据));
//内存映射共享内存对象
*共享内存=(共享数据*)mmap(0,sizeof(共享数据),PROT_WRITE,MAP_shared,*shm_fd,0);
//创建子进程
int-pid;
//如果出现错误,则返回-1
如果((pid=fork())=-1){
perror(“未能创建子进程”);
退出(1);//终止父进程
}
//否则,返回由fork创建的pid
返回pid;
}
/********************************
*格特·科拉兹()
*
*返回运行的结果
*输入n通过
*collatz猜想函数。
********************************/
int get_collatz(int n){
返回(!(n%2))?(n/2):(3*n+1);
}
这是控制台输出的外观:
有趣的是,如果我在从共享内存打印子进程的结果之前,向父进程添加一个带有新行的print语句,如下所示:
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
do{
int-pid;
printf(“\n”);
//创建具有共享内存空间的子进程
pid=创建子对象(&name,&shm\u fd,&shared\u内存);
//母公司
如果(pid>0){
等待(空);
//打印collatz结果
int i;
对于(i=0;isize;i++)
printf(“%d”,共享内存->num[i]);
//如果这只是序列的一部分
//然后在最后一个序列值的collatz处开始下一个序列
如果(共享内存->部分)
n=get_collatz(共享内存->num[MAX_SEQUENCE-1]);
}
//孩子
然后,打印语句将被输出正确的次数
另一个有趣的事实是,只有将换行打印语句放在create_child()调用之前,此解决方案才有效,而不是放在create_child()调用之后
我不希望这些语句被新行分隔,我希望它们都打印在一行上。知道是什么导致了这些额外的打印语句吗?您需要添加适当的刷新调用,或者需要更改标准输出,使其不被缓冲 库正在努力提高效率,直到有一个完整的行时才真正写入终端。因此,它将部分行存储在缓冲区中。当您使用
fork
时,您将得到两个基本相同的进程,即,