【发布时间】:2018-05-09 05:28:16
【问题描述】:
我正在我的程序中执行一些物理计算,其中需要将输出存储到临时缓冲区并通过管道传递。
缓冲区需要共享不同的数据类型:首先,我需要存储我正在学习的主题的名称;其次是我的计算结果(所有float 数字)。
代码如下所示:
initialdata.dat
Aston Martin Vantage V12|07.7|090
Ferrari LaFerrari |09.6|111
Lamborghini Aventador |09.6|097
Porsche 911 Turbo S |09.6|092
Tesla Model S P100D |10.0|069
Hennessey Venom GT |10.3|120
Bugatti Chiron |11.2|114
Koenigsegg Agera |10.3|121
Main.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define READ 0
#define WRITE 1
#define M 2 // Number of subjects.
int main(){
int pipeToChild[2];
if (pipe(pipeToChild) < 0) {
fprintf(stderr,"Error in pipe!");
return -1;
}
pid_t pid[M];
srand (time(NULL));
// Declares the file pointer with the information.
FILE * pFile;
char buffer[34]; // Buffer where subject info is sent to childs.
char tempBuffer[50]; // The buffer that causes problems.
pFile = fopen ("initialdata.dat","r");
for(int i = 0; i < M; i++){
pid[i] = fork();
if (pid[i] < 0){
printf("Fork error!\n");
return -1;
}
else if(pid[i]==0){
// Creates the pipes (one per child) to pass the temporary buffer to the results process (still not created).
int pipeToResults[2];
if (pipe(pipeToResults) < 0) {
fprintf(stderr,"Error in pipe!");
return -1;
}
// Receives the car information from the file through a pipe.
char receivedValue[34];
receivedValue[33] = '\0';
close(pipeToChild[WRITE]);
read(pipeToChild[READ], receivedValue, sizeof(receivedValue));
// Processes the information and tokenizes it.
char name[25];
char CHARacceleration[6];
char CHARmaxSpeed[4];
strcpy(name, strtok(receivedValue, "|"));
strcpy(CHARacceleration, strtok(NULL, "|"));
strcpy(CHARmaxSpeed, strtok(NULL, "|"));
float acceleration = atof(CHARacceleration);
float maxSpeed = atoi(CHARmaxSpeed);
// Adds 0.0X to acceleration.
float randomNum = rand() % 5;
acceleration = acceleration + randomNum/100;
float distance = 0;
float TA = 0; // Time using Uniformly Accelerated Linear Motion.
float TB = 0; // Time using Linear Motion.
float TE = 0.5; // Time increment.
float currentVelocity = 0; // In m/s.
// Applies different physical calculations depending on the case.
while (distance <= 1000){
TA += TE;
if (currentVelocity < maxSpeed){ // Acceleration > 0
distance = (acceleration*pow((TA),2))/2;
currentVelocity = acceleration*TA;
distance = 2*distance;
}
else{ // Acceleration = 0
TB += TE;
currentVelocity = maxSpeed;
distance += maxSpeed*TB;
}
}
// Debug purposes, just for ensuring everything gets processed the right way.
printf("Name: %s\n", name);
printf("Distance: %.2f m\n", distance);
printf("Time: %.2f s\n", TA+TB);
printf("Max speed reached: %.2f km/h\n", currentVelocity*3.6);
printf("Acceleration: %.2f m/s^2\n", acceleration);
printf("\n");
// Comment this if you want to switch between the situations I talked about.
sprintf(tempBuffer, "%s %.2f %.2f %.2f %.2f", name, distance, TA+TB, currentVelocity, acceleration);
printf("Buffer: %s\n\n", tempBuffer);
exit(0);
}
else if(pid[i]>0){
// Generates a random subject from the list. Buggy section, fixed it the best way I could.
int randCar = rand() % 15 + 1;
if (randCar % 2 == 0)
randCar--;
for (int i = 1; i <= randCar; i++){
if (pFile != NULL)
fgets (buffer, sizeof(buffer), pFile);
else
perror ("ERROR reading file!");
}
char toSend[34]; //This will be passed through the `pipeToChild` pipe.
strcpy(toSend, buffer);
// Loads pipe.
close(pipeToChild[READ]);
write(pipeToChild[WRITE], toSend, strlen(toSend));
close(pipeToChild[WRITE]);
}
}
for (int i=0;i<M;i++){
waitpid(pid[i], NULL, 0);
}
fclose(pFile);
return 0;
}
不过,输出会有所不同,具体取决于我是否使用sprintf。例如,对于 M=2,输出应该是:
案例一:否sprintf:
I'm the child process 1 with PID 12304
Name: Bugatti Chiron
Distance: 1012.61 m
Time: 9.50 s
Max speed reached: 383.72 km/h
Aceleration: 11.22 m/s^2
I'm the child process 2 with PID 12305
Name: Bugatti Chiron
Distance: 1012.61 m
Time: 9.50 s
Max speed reached: 383.72 km/h
Aceleration: 11.22 m/s^2
案例 2:sprintf:
I'm the child process 2 with PID 12307
I'm the child process 1 with PID 12306
Name: Bugatti Chiron
Distance: 1012.61 m
Time: 9.50 s
Max speed reached: 383.72 km/h
Aceleration: 11.22 m/s^2
Buffer: Bugatti Chiron 1012.61 9.50 383.82 11.22
“冲刺”有什么问题?为什么这条线搞砸了整个程序?
编辑:该程序是一个简单的飙车模拟器,其中 M 辆汽车在 1000 米直线上竞争。 master 进程创建 M 辆随机汽车(尽管此功能未正确实现),并通过单个管道将存储在 .dat 文件中的一些数据传递给 M 个子进程。
每辆车都是一个子进程,在其中进行计算。一旦我们得到这些值,每个子进程都会通过自己的管道将存储在临时缓冲区中的数据传递给一个results进程,该进程将它们存储在输出文件中。请注意,此功能仍未实现,因为首先我需要设法创建缓冲区。我的问题只是关于缓冲区问题。
【问题讨论】:
-
如果没有Minimal, Complete, and Verifiable Example,就很难说出任何具体的内容,我们所能做的就是猜测(并且可能猜错了)。请read about how to ask good questions.
-
一个猜测:这是由于您无法控制调度程序的进程,额外的
sprintf调用可能会导致调度程序意外切换进程?这与输出缓冲一起可能会导致多进程程序中的输出问题。 -
带有注释
// printf的...很可能是个问题。如果您调用printf并且不刷新输出缓冲区,然后调用fork,您将获得重复的输出。尝试在循环末尾添加flush。 -
已更新完整代码。
标签: c linux operating-system printf system-calls