2017-11-25 293 views
0

我在我的程序中執行一些物理計算,其中輸出需要存儲到臨時緩衝區並通過管道。如何在C中創建臨時緩衝區?

緩衝區需要共享不同的數據類型:首先,我需要存儲我研究這一課題的名稱;其次是我的計算結果(全部爲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,輸出應該是:

案例1:沒有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的過程,將它們存儲在輸出文件通過存儲在臨時緩衝區中的數據。請注意,此功能仍未實現,因爲首先我需要管理創建緩衝區。我的問題是只有關於緩衝區問題。

enter image description here

+0

沒有[最小,**完整**和可驗證示例](http:// stackoverflow。com/help/mcve)它很難說任何具體的東西,我們所能做的只是猜測*(可能猜得不好)。並請[請閱讀如何提出良好問題](http://stackoverflow.com/help/how-to-ask)。 –

+0

猜測雖然:這是因爲你無法控制調度程序的進程,並且額外的'sprintf'調用可能會導致調度程序意外切換進程?與輸出緩衝一起可能導致多進程程序中的輸出問題。 –

+0

帶有註釋'// printf'的'...'很可能是一個問題。如果您調用'printf'並且不刷新輸出緩衝區,然後調用fork,則將獲得重複的輸出。嘗試在循環結尾添加一個'flush'。 –

回答

1

當你fork,創建一個新的進程。如果沒有任何類型的同步,則創建的兩個子進程將同時運行。因此,每個孩子的輸出可能會相互交錯,具體取決於操作系統如何決定安排每個進程。 sprintf的存在並不會改變這一點。

你可能需要通過管道傳遞消息得到處理相互同步到時他們每個人的打印控制。

0

char tempBuffer[50];被初始化爲50而不是34,這是我發送的數據的精確大小。

+0

但是請注意,如果每個浮點數用7個字符表示,並且每個數字之間有1個空格,那麼緩衝區溢出的標題或'6'字符就是'31'chars +'25'個字符。你剛剛推出了紅地毯*未定義的行爲*。不要跳過緩衝區大小,'256'應該在這裏留出足夠的空間。 –

相關問題