ошибка сегментации в fork () - PullRequest
0 голосов
/ 26 июня 2018

У меня возникают некоторые проблемы, когда я пытаюсь сделать многопроцессорную программу на Raspberry Pi. Существует только два процесса: один для чтения данных из аналого-цифрового преобразователя и другой процесс, который получает эти данные по каналу и отправляет их на ПК по протоколу UDP. Обе программы были протестированы по отдельности, и они работают очень хорошо, проблема, с которой я сталкиваюсь, заключается в том, что при попытке выполнить их через многопроцессорную программу у меня возникает ошибка сбоя сегментации, которая не позволяет мне создавать два моих процесса. Ошибка появляется при вызове функции fork ().

Это код, который я пытаюсь заставить работать:

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "ADS1256_DAC8532_lib.h"
#include "addstrings2.h"
#include "changetypes.h"
#include "ReadWriteSock.h"
#include "Socket.h"



int main(){
//Variables for the first program: reading the ADC
int32_t adc[3];
uint8_t ch_num;
//variables for the UDP protocol program
struct sockaddr_in Directionwrite;
int Descriptor,aux;
struct sockaddr_in Recv;
int RecvAddrSize=sizeof(Recv);

//General variables that are needed in all our programs

int variable;
float *servo=0;
float *pressure1=0;
float *position=0;
float *pressure2=0;
char SendDataADC[11];
char press1[5];
char press2[5];
char pos[5];
char cservo[5];
int ppres1[2];
int ppres2[2];
int ppos[2];
int pservo [2];
pipe(ppres1);
pipe(ppres2);
pipe(ppos);
pipe(pservo);
if(fork()){
    //Father process
            bcm2835_init();
            bcm2835_spi_begin();
            bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST );      // The default
            bcm2835_spi_setDataMode(BCM2835_SPI_MODE1);                   // The default
            bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_8192); // The default
            bcm2835_gpio_fsel(SPICS, BCM2835_GPIO_FSEL_OUTP);//
            bcm2835_gpio_write(SPICS, HIGH);
            bcm2835_gpio_fsel(DRDY, BCM2835_GPIO_FSEL_INPT);
            bcm2835_gpio_set_pud(DRDY, BCM2835_GPIO_PUD_UP); 

            ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);
            ADS1256_StartScan(1);
            ch_num=3;
            while(1){
                while((ADS1256_Scan() == 0));
                for (unsigned int i = 0; i < ch_num; i++){
                    adc[i] = ADS1256_GetAdc(i);
                    adc[i] = (adc[i] * 100) / 167;  
                    switch(i){
                        case 0:
                                    *position=adc[i]<<2;
                                    passtochar(*position,pos);
                                    write(ppos[1],pos,4);
                                     break;    //We multiply the ADC value of our position sensor by 4 beacuse we are going to have an electronical circuit that is going to amplify our signal by a factor of 0.25 so it can be read by our Rpi  
                        case 1: 
                                *pressure1=adc[i]; 
                                passtochar(*pressure1,press1);
                                write(ppres1[1],press1,4);
                                break;     //The pressure sensors do not need to be a,plified i order to be read, thay are only going to have a filter to reduce the amount of noise read
                        case 2:
                            *pressure2=adc[i];
                            passtochar(*pressure2,press2);
                            write(ppres2[1],press2,4);
                             break;
                        default: break;
                    }
                }
                    read(pservo[0],cservo,4);
                    *servo=passtofloat(cservo);
                    *servo=*servo/8;    //Si c'est entre -10 et 10 le voltage au servo, on le regle pour 0 20 et apres on l'adjustera avec un circuit electronique. 20/4 sont 5v, notre limite(trop juste, et le programme peut faire erreurs de precision), on utilise 8 pour être secures.
                    Write_DAC8552(0x30, Voltage_Convert(5.0, *servo));
               //printf("Bucle de ADC \r\n");
               usleep(1000);
           }
           bcm2835_spi_end();
           bcm2835_close();
            }
    else{   
    //Child process
            Directionwrite.sin_family = AF_INET;
            Directionwrite.sin_addr.s_addr=inet_addr("169.254.51.37");
            Directionwrite.sin_port = htons(59212);

                Descriptor = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                printf("\n Llego");
                aux=connect(Descriptor, (struct sockaddr *)&Directionwrite, sizeof (Directionwrite));
                            printf("\n aux=%d, aux);
            while(1){
                printf("Dentro del bucle socket");
                read(ppres1[0],press1,4);
                read(ppres2[0],press2,4);
                read(ppos[0],ppos,4);
                write(pservo[1],cservo,4);
                addstringsADCv2(SendDataADC,press1,press2,pos);
                writeSocket(Descriptor,SendDataADC,strlen(SendDataADC));
                //int b=readSocket(Descriptor,servo,5);
                int b=recvfrom(Descriptor, cservo,5,0,(struct sockaddr *) &Recv, &RecvAddrSize);
                cservo[4]='\0';
                write(pservo[1],cservo,4);
                printf("\n %d", b);
                printf("\n Hemos recibido el valor: %s", cservo);
                }
            }              
        }
return 0;

}

Что касается некоторых функций, вызываемых в программе, passtochar - это созданная мною функция, которая запрашивает два параметра (значение с плавающей запятой и вектор символа) и преобразует значение с плавающей запятой в ASCII и сохраняет его в вектор. Что касается функции addstringsADCv2, она просто получает несколько векторов символов и помещает их в один, который больше. Заранее спасибо за любую возможную помощь.

...