使用BeagleBone Black读取两个串行端口时出现分段错误错误

时间:2018-10-11 18:35:45

标签: linux gps segmentation-fault uart beagleboneblack

在Beaglebone Black上使用Debian GNU / Linux 7.4读取两条不同的串行通信线路时,出现分段错误错误。其中之一是CAN-BUS数据。我正在使用can-utils软件包来使用Waveshares RS485 / CAN CAPE模块。 “ https://github.com/linux-can/can-utils/blob/master/candump.c

CAN log file

另一个是通过称为uBlox GY-NEO6MV2模块的GPS模块的UART数据。对于GPS,我有此代码,可以很好地工作;

    #include <stdio.h>
    #include <fcntl.h>   /* File Control Definitions           */
    #include <termios.h> /* POSIX Terminal Control Definitions */
    #include <unistd.h>  /* UNIX Standard Definitions      */ 
    #include <errno.h>   /* ERROR Number Definitions           */
    #include <string.h>  /* Array to String                   */ 

void main(void){
        int fd;/*File Descriptor*/


    /*------------------------------- Opening the Serial Port -------------------------------*/

    /* Change /dev/ttyUSB0 to the one corresponding to your system */
    while(1){
        fd = open("/dev/ttyO2",O_RDWR | O_NOCTTY);  /* ttyUSB0 is the FT232 based USB2SERIAL Converter   */
                            /* O_RDWR   - Read/Write access to serial port       */
                            /* O_NOCTTY - No terminal will control the process   */
                            /* Open in blocking mode,read will wait              */



        if(fd == -1)                        /* Error Checking */
               printf("\n  Error! in Opening ttyO2  ");
        else
               printf("\n  ttyO2 Opened Successfully ");


        /*---------- Setting the Attributes of the serial port using termios structure --------- */

        struct termios SerialPortSettings;  /* Create the structure                          */

        tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */

        /* Setting the Baud rate */
        cfsetispeed(&SerialPortSettings,B9600); /* Set Read  Speed as 9600                       */
        cfsetospeed(&SerialPortSettings,B9600); /* Set Write Speed as 9600                       */

        /* 8N1 Mode */
        SerialPortSettings.c_cflag &= ~PARENB;   /* Disables the Parity Enable bit(PARENB),So No Parity   */
        SerialPortSettings.c_cflag &= ~CSTOPB;   /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
        SerialPortSettings.c_cflag &= ~CSIZE;    /* Clears the mask for setting the data size             */
        SerialPortSettings.c_cflag |=  CS8;      /* Set the data bits = 8                                 */

        SerialPortSettings.c_cflag &= ~CRTSCTS;       /* No Hardware flow Control                         */
        SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines       */ 


        SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);          /* Disable XON/XOFF flow control both i/p and o/p */
        SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Non Cannonical mode                            */

        SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/

        /* Setting Time outs */
        SerialPortSettings.c_cc[VMIN] = 42; /* Read at least 51 characters */
        SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly   */


        if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
            printf("\n  ERROR ! in Setting attributes");
        else
            printf("\n  BaudRate = 9600 \n  StopBits = 1 \n  Parity   = none  \n\n");

        /*------------------------------- Read data from serial port -----------------------------*/

        tcflush(fd, TCIFLUSH);   /* Discards old data in the rx buffer            */

        char read_buffer[42];   /* Buffer to store the data received              */
        int  bytes_read = 0;    /* Number of bytes read by the read() system call */
        int ia = 0; int a;
        int test = 0;
        char new_read[38];
        char curr_read[33];
        a = 0;
        do{
            bytes_read = read(fd,&read_buffer,42); /* Read the data                   */

            if(read_buffer[0] == '$')
                if(read_buffer[1] == 'G')
                    if(read_buffer[2] == 'P')
                        if(read_buffer[3] == 'G')
                            if(read_buffer[4] == 'G'){
                                for(ia=7;ia<bytes_read;ia++){    /*printing only the received characters*/
                                    new_read[a] = read_buffer[ia];
                                    printf("%c",read_buffer[ia]);
                                    a = a+1;
                                    test = 1;
                                }
                                strcpy(curr_read, new_read);
                                printf("\n%s \n", curr_read);
                            }
                            else
                                test = 0;
                        else
                            test = 0;
                    else
                        test = 0;
                else
                    test = 0;
            else
                test = 0;
        }while(test == 0);
        close(fd); /* Close the serial port */
    }

}

对于CAN记录,我正在使用上面链接中的代码。我试图达到的目标是将两个数据记录到同一日志文件中。我对上面的代码进行了一些修改,以仅获取所需的数据。这是时间戳和位置坐标。

GPS edited data

GPS模块每秒发送一次数据,所以我正试图从GPS中获取一个数据并将其附加到下一个1000 CAN数据中,然后写入.log文件,然后从GPS读取新值。 GPS模块的通信比特率为9600kbps,CAN比特率为125000 kbps。 GPS连接到UART2引脚,CAN连接到UART1。当我尝试将两个代码合并为一个时,出现 Segmentation fault 错误。我对紫色的已恢复内存空间进行了一些研究,研究了它的UNIX错误代码。但是,当单独工作时,这两个代码可以完美地工作。这就是我卡住的地方。 我尝试合并的代码就像;

/* for hardware timestamps - since Linux 2.6.30 */
#ifndef SO_TIMESTAMPING
#define SO_TIMESTAMPING 37
#endif

/* from #include <linux/net_tstamp.h> - since Linux 2.6.30 */
#define SOF_TIMESTAMPING_SOFTWARE (1<<4)
#define SOF_TIMESTAMPING_RX_SOFTWARE (1<<3)
#define SOF_TIMESTAMPING_RAW_HARDWARE (1<<6)

#define MAXSOCK 16    /* max. number of CAN interfaces given on the cmdline */
#define MAXIFNAMES 30 /* size of receive name index to omit ioctls */
#define MAXCOL 6      /* number of different colors for colorized output */
#define ANYDEV "any"  /* name of interface to receive from any CAN interface */
#define ANL "\r\n"    /* newline in ASC mode */

#define SILENT_INI 42 /* detect user setting on commandline */
#define SILENT_OFF 0  /* no silent mode */
#define SILENT_ANI 1  /* silent mode with animation */
#define SILENT_ON  2  /* silent mode (completely silent) */

static char *cmdlinename[MAXSOCK];
static __u32 dropcnt[MAXSOCK];
static __u32 last_dropcnt[MAXSOCK];
static char devname[MAXIFNAMES][IFNAMSIZ+1];
static int  dindex[MAXIFNAMES];
static int  max_devname_len; /* to prevent frazzled device name output */ 
const int canfd_on = 1;

#define MAXANI 4
const char anichar[MAXANI] = {'|', '/', '-', '\\'};
const char extra_m_info[4][4] = {"- -", "B -", "- E", "B E"};

extern int optind, opterr, optopt;

static volatile int running = 1;

void sigterm(int signo)
{
    running = 0;
}

int idx2dindex(int ifidx, int socket) {

    int i;
    struct ifreq ifr;

    for (i=0; i < MAXIFNAMES; i++) {
        if (dindex[i] == ifidx)
            return i;
    }

    /* create new interface index cache entry */

    /* remove index cache zombies first */
    for (i=0; i < MAXIFNAMES; i++) {
        if (dindex[i]) {
            ifr.ifr_ifindex = dindex[i];
            if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
                dindex[i] = 0;
        }
    }

    for (i=0; i < MAXIFNAMES; i++)
        if (!dindex[i]) /* free entry */
            break;

    if (i == MAXIFNAMES) {
        fprintf(stderr, "Interface index cache only supports %d interfaces.\n",
               MAXIFNAMES);
        exit(1);
    }

    dindex[i] = ifidx;

    ifr.ifr_ifindex = ifidx;
    if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
        perror("SIOCGIFNAME");

    if (max_devname_len < strlen(ifr.ifr_name))
        max_devname_len = strlen(ifr.ifr_name);

    strcpy(devname[i], ifr.ifr_name);

#ifdef DEBUG
    printf("new index %d (%s)\n", i, devname[i]);
#endif

    return i;
}

int main(int argc, char **argv)
{
    fd_set rdfs;
    int s[MAXSOCK];
    int bridge = 0;
    useconds_t bridge_delay = 0;
    unsigned char timestamp = 0;
    unsigned char hwtimestamp = 0;
    unsigned char down_causes_exit = 1;
    unsigned char dropmonitor = 0;
    unsigned char extra_msg_info = 0;
    unsigned char silent = SILENT_INI;
    unsigned char silentani = 0;
    unsigned char color = 0;
    unsigned char view = 0;
    unsigned char log = 0;
    unsigned char logfrmt = 0;
    int count = 0;
    int rcvbuf_size = 0;
    int opt, ret;
    int currmax, numfilter;
    int join_filter;
    char *ptr, *nptr;
    struct sockaddr_can addr;
    char ctrlmsg[CMSG_SPACE(sizeof(struct timeval) + 3*sizeof(struct timespec) + sizeof(__u32))];
    struct iovec iov;
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct can_filter *rfilter;
    can_err_mask_t err_mask;
    struct canfd_frame frame;
    int nbytes, i, maxdlen;
    struct ifreq ifr;
    struct timeval tv, last_tv;
    struct timeval timeout, timeout_config = { 0, 0 }, *timeout_current = NULL;
    FILE *logfile = NULL;

    int fd;/*File Descriptor*/
    struct termios SerialPortSettings;  /* Create the structure                          */


    signal(SIGTERM, sigterm);
    signal(SIGHUP, sigterm);
    signal(SIGINT, sigterm);

    last_tv.tv_sec  = 0;
    last_tv.tv_usec = 0;

    if (optind == argc) {
        print_usage(basename(argv[0]));
        exit(0);
    }

    if (logfrmt && view) {
        fprintf(stderr, "Log file format selected: Please disable ASCII/BINARY/SWAP options!\n");
        exit(0);
    }

    if (silent == SILENT_INI) {
        if (log) {
            fprintf(stderr, "Disabled standard output while logging.\n");
            silent = SILENT_ON; /* disable output on stdout */
        } else
            silent = SILENT_OFF; /* default output */
    }

    currmax = argc - optind; /* find real number of CAN devices */

    if (currmax > MAXSOCK) {
        fprintf(stderr, "More than %d CAN devices given on commandline!\n", MAXSOCK);
        return 1;
    }

    for (i=0; i < currmax; i++) {

        ptr = argv[optind+i];
        nptr = strchr(ptr, ',');

#ifdef DEBUG
        printf("open %d '%s'.\n", i, ptr);
#endif

        s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
        if (s[i] < 0) {
            perror("socket");
            return 1;
        }

        cmdlinename[i] = ptr; /* save pointer to cmdline name of this socket */

        if (nptr)
            nbytes = nptr - ptr;  /* interface name is up the first ',' */
        else
            nbytes = strlen(ptr); /* no ',' found => no filter definitions */

        if (nbytes >= IFNAMSIZ) {
            fprintf(stderr, "name of CAN device '%s' is too long!\n", ptr);
            return 1;
        }

        if (nbytes > max_devname_len)
            max_devname_len = nbytes; /* for nice printing */

        addr.can_family = AF_CAN;

        memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
        strncpy(ifr.ifr_name, ptr, nbytes);

#ifdef DEBUG
        printf("using interface name '%s'.\n", ifr.ifr_name);
#endif

        if (strcmp(ANYDEV, ifr.ifr_name)) {
            if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
                perror("SIOCGIFINDEX");
                exit(1);
            }
            addr.can_ifindex = ifr.ifr_ifindex;
        } else
            addr.can_ifindex = 0; /* any can interface */

        if (nptr) {

            /* found a ',' after the interface name => check for filters */

            /* determine number of filters to alloc the filter space */
            numfilter = 0;
            ptr = nptr;
            while (ptr) {
                numfilter++;
                ptr++; /* hop behind the ',' */
                ptr = strchr(ptr, ','); /* exit condition */
            }

            rfilter = malloc(sizeof(struct can_filter) * numfilter);
            if (!rfilter) {
                fprintf(stderr, "Failed to create filter space!\n");
                return 1;
            }

            numfilter = 0;
            err_mask = 0;
            join_filter = 0;

            while (nptr) {

                ptr = nptr+1; /* hop behind the ',' */
                nptr = strchr(ptr, ','); /* update exit condition */

                if (sscanf(ptr, "%x:%x",
                       &rfilter[numfilter].can_id, 
                       &rfilter[numfilter].can_mask) == 2) {
                    rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
                    numfilter++;
                } else if (sscanf(ptr, "%x~%x",
                          &rfilter[numfilter].can_id, 
                          &rfilter[numfilter].can_mask) == 2) {
                    rfilter[numfilter].can_id |= CAN_INV_FILTER;
                    rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
                    numfilter++;
                } else if (*ptr == 'j' || *ptr == 'J') {
                    join_filter = 1;
                } else if (sscanf(ptr, "#%x", &err_mask) != 1) { 
                    fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr);
                    return 1;
                }
            }

            if (err_mask)
                setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
                       &err_mask, sizeof(err_mask));

            if (join_filter && setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS,
                              &join_filter, sizeof(join_filter)) < 0) {
                perror("setsockopt CAN_RAW_JOIN_FILTERS not supported by your Linux Kernel");
                return 1;
            }

            if (numfilter)
                setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
                       rfilter, numfilter * sizeof(struct can_filter));

            free(rfilter);

        } /* if (nptr) */

        /* try to switch the socket into CAN FD mode */
        setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on));

        if (rcvbuf_size) {

            int curr_rcvbuf_size;
            socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size);

            /* try SO_RCVBUFFORCE first, if we run with CAP_NET_ADMIN */
            if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUFFORCE,
                       &rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
#ifdef DEBUG
                printf("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n");
#endif
                if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
                           &rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
                    perror("setsockopt SO_RCVBUF");
                    return 1;
                }

                if (getsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
                           &curr_rcvbuf_size, &curr_rcvbuf_size_len) < 0) {
                    perror("getsockopt SO_RCVBUF");
                    return 1;
                }

                /* Only print a warning the first time we detect the adjustment */
                /* n.b.: The wanted size is doubled in Linux in net/sore/sock.c */
                if (!i && curr_rcvbuf_size < rcvbuf_size*2)
                    fprintf(stderr, "The socket receive buffer size was "
                        "adjusted due to /proc/sys/net/core/rmem_max.\n");
            }
        }

        if (timestamp || log || logfrmt) {

            if (hwtimestamp) {
                const int timestamping_flags = (SOF_TIMESTAMPING_SOFTWARE | \
                                SOF_TIMESTAMPING_RX_SOFTWARE | \
                                SOF_TIMESTAMPING_RAW_HARDWARE);

                if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMPING,
                        &timestamping_flags, sizeof(timestamping_flags)) < 0) {
                    perror("setsockopt SO_TIMESTAMPING is not supported by your Linux kernel");
                    return 1;
                }
            } else {
                const int timestamp_on = 1;

                if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP,
                           &timestamp_on, sizeof(timestamp_on)) < 0) {
                    perror("setsockopt SO_TIMESTAMP");
                    return 1;
                }
            }
        }

        if (dropmonitor) {

            const int dropmonitor_on = 1;

            if (setsockopt(s[i], SOL_SOCKET, SO_RXQ_OVFL,
                       &dropmonitor_on, sizeof(dropmonitor_on)) < 0) {
                perror("setsockopt SO_RXQ_OVFL not supported by your Linux Kernel");
                return 1;
            }
        }

        if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
            perror("bind");
            return 1;
        }
    }

    if (log) {
        time_t currtime;
        struct tm now;
        char fname[sizeof("candump-2006-11-20_202026.log")+1];

        if (time(&currtime) == (time_t)-1) {
            perror("time");
            return 1;
        }

        localtime_r(&currtime, &now);

        sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
            now.tm_year + 1900,
            now.tm_mon + 1,
            now.tm_mday,
            now.tm_hour,
            now.tm_min,
            now.tm_sec);

        if (silent != SILENT_ON)
            printf("\nWarning: console output active while logging!");

        fprintf(stderr, "\nEnabling Logfile '%s'\n\n", fname);

        logfile = fopen(fname, "w");
        if (!logfile) {
            perror("logfile");
            return 1;
        }
    }

    /* these settings are static and can be held out of the hot path */
    iov.iov_base = &frame;
    msg.msg_name = &addr;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = &ctrlmsg;

    while (running) {

        /*------------------------------- Opening the Serial Port -------------------------------*/

        /* Change /dev/ttyUSB0 to the one corresponding to your system */

        fd = open("/dev/ttyO2",O_RDWR | O_NOCTTY);  /* ttyUSB0 is the FT232 based USB2SERIAL Converter   */
                            /* O_RDWR   - Read/Write access to serial port       */
                            /* O_NOCTTY - No terminal will control the process   */
                            /* Open in blocking mode,read will wait              */


                                    /* Error Checking */
        if(fd == -1)                        
               printf("\n  Error! in Opening ttyO2  ");
        else
               printf("\n  ttyO2 Opened Successfully ");


        /*---------- Setting the Attributes of the serial port using termios structure --------- */

        //struct termios SerialPortSettings;    /* Create the structure                          */

        tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */

        /* Setting the Baud rate */
        cfsetispeed(&SerialPortSettings,B9600); /* Set Read  Speed as 9600                       */
        cfsetospeed(&SerialPortSettings,B9600); /* Set Write Speed as 9600                       */

        /* 8N1 Mode */
        SerialPortSettings.c_cflag &= ~PARENB;   /* Disables the Parity Enable bit(PARENB),So No Parity   */
        SerialPortSettings.c_cflag &= ~CSTOPB;   /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
        SerialPortSettings.c_cflag &= ~CSIZE;    /* Clears the mask for setting the data size             */
        SerialPortSettings.c_cflag |=  CS8;      /* Set the data bits = 8                                 */

        SerialPortSettings.c_cflag &= ~CRTSCTS;       /* No Hardware flow Control                         */
        SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines       */ 


        SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);          /* Disable XON/XOFF flow control both i/p and o/p */
        SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Non Cannonical mode                            */

        SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/

        /* Setting Time outs */
        SerialPortSettings.c_cc[VMIN] = 42; /* Read at least 42 characters */
        SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly   */


        if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
            printf("\n  ERROR ! in Setting attributes");
        else
            printf("\n  BaudRate = 9600 \n  StopBits = 1 \n  Parity   = none  \n\n");

        /*------------------------------- Read data from serial port -----------------------------*/

        tcflush(fd, TCIFLUSH);   /* Discards old data in the rx buffer */

        char read_buffer[42];   /* Buffer to store the data received              */
        int  bytes_read = 0;    /* Number of bytes read by the read() system call */
        int ia = 0; int a;
        int test = 0;
        char new_read[38];
        char curr_read[33];
        int countc = 0;
        a = 0;
        do{
            bytes_read = read(fd,&read_buffer,42); /* Read the data                   */

            if(read_buffer[0] == '$')
                if(read_buffer[1] == 'G')
                    if(read_buffer[2] == 'P')
                        if(read_buffer[3] == 'G')
                            if(read_buffer[4] == 'G'){
                                for(ia=7;ia<bytes_read;ia++){    /*printing only the received characters*/
                                    new_read[a] = read_buffer[ia];
                                    //printf("%c",read_buffer[ia]);
                                    a = a+1;
                                    test = 1;
                                }
                                strcpy(curr_read, new_read);
                                //printf("\n%s \n", curr_read);
                            }
                            else
                                test = 0;
                        else
                            test = 0;
                    else
                        test = 0;
                else
                    test = 0;
            else
                test = 0;
        }while(test == 0);

        //tcflush(fd, TCIFLUSH);   /* Discards old data in the rx buffer */

        close(fd); /* Close the serial port */

        while(countc < 1000){
            FD_ZERO(&rdfs);
            for (i=0; i<currmax; i++)
                FD_SET(s[i], &rdfs);

            if (timeout_current)
                *timeout_current = timeout_config;

            if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, timeout_current)) <= 0) {
                //perror("select");
                running = 0;
                continue;
            }

            for (i=0; i<currmax; i++) {  /* check all CAN RAW sockets */

                if (FD_ISSET(s[i], &rdfs)) {

                    int idx;

                    /* these settings may be modified by recvmsg() */
                    iov.iov_len = sizeof(frame);
                    msg.msg_namelen = sizeof(addr);
                    msg.msg_controllen = sizeof(ctrlmsg);  
                    msg.msg_flags = 0;

                    nbytes = recvmsg(s[i], &msg, 0);
                    idx = idx2dindex(addr.can_ifindex, s[i]);

                    if (nbytes < 0) {
                        if ((errno == ENETDOWN) && !down_causes_exit) {
                            fprintf(stderr, "%s: interface down\n", devname[idx]);
                            continue;
                        }
                        perror("read");
                        return 1;
                    }

                    if ((size_t)nbytes == CAN_MTU)
                        maxdlen = CAN_MAX_DLEN;
                    else if ((size_t)nbytes == CANFD_MTU)
                        maxdlen = CANFD_MAX_DLEN;
                    else {
                        fprintf(stderr, "read: incomplete CAN frame\n");
                        return 1;
                    }

                    if (count && (--count == 0))
                        running = 0;

                    if (bridge) {
                        if (bridge_delay)
                            usleep(bridge_delay);

                        nbytes = write(bridge, &frame, nbytes);
                        if (nbytes < 0) {
                            perror("bridge write");
                            return 1;
                        } else if ((size_t)nbytes != CAN_MTU && (size_t)nbytes != CANFD_MTU) {
                            fprintf(stderr,"bridge write: incomplete CAN frame\n");
                            return 1;
                        }
                    }

                    for (cmsg = CMSG_FIRSTHDR(&msg);
                        cmsg && (cmsg->cmsg_level == SOL_SOCKET);
                        cmsg = CMSG_NXTHDR(&msg,cmsg)) {
                        if (cmsg->cmsg_type == SO_TIMESTAMP) {
                            memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
                        } else if (cmsg->cmsg_type == SO_TIMESTAMPING) {

                            struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);

                            /*
                            * stamp[0] is the software timestamp
                            * stamp[1] is deprecated
                            * stamp[2] is the raw hardware timestamp
                            * See chapter 2.1.2 Receive timestamps in
                            * linux/Documentation/networking/timestamping.txt
                            */
                            tv.tv_sec = stamp[2].tv_sec;
                            tv.tv_usec = stamp[2].tv_nsec/1000;
                        } else if (cmsg->cmsg_type == SO_RXQ_OVFL)
                            memcpy(&dropcnt[i], CMSG_DATA(cmsg), sizeof(__u32));
                    }

                    /* check for (unlikely) dropped frames on this specific socket */
                    if (dropcnt[i] != last_dropcnt[i]) {

                        __u32 frames = dropcnt[i] - last_dropcnt[i];

                        if (silent != SILENT_ON)
                            printf("DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
                                frames, (frames > 1)?"s":"", devname[idx], dropcnt[i]);

                        if (log)
                            fprintf(logfile, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
                                frames, (frames > 1)?"s":"", devname[idx], dropcnt[i]);

                        last_dropcnt[i] = dropcnt[i];
                    }

                    /* once we detected a EFF frame indent SFF frames accordingly */
                    if (frame.can_id & CAN_EFF_FLAG)
                        view |= CANLIB_VIEW_INDENT_SFF;

                    if (log) {                                                  /*   CODE GETS IN TO THIS PART  */
                        char buf[CL_CFSZ]; /* max length */                     /*   WHEN PRINTING INTO FILE    */
                                                                                /*                              */
                        /* log CAN frame with absolute timestamp & device */    /*                              */
                        sprint_canframe(buf, &frame, 0, maxdlen);               /*                              */
                        fprintf(logfile, "%s %*s %s\n",                         /*                              */
                            curr_read,                                          /*                              */
                            max_devname_len, devname[idx], buf);                /*                              */
                    }                                                           /*                              */

                    if (logfrmt) {
                        char buf[CL_CFSZ]; /* max length */

                        /* print CAN frame in log file style to stdout */
                        sprint_canframe(buf, &frame, 0, maxdlen);
                        printf("(%010ld.%06ld) %*s %s\n",
                            tv.tv_sec, tv.tv_usec,
                            max_devname_len, devname[idx], buf);
                        goto out_fflush; /* no other output to stdout */
                    }

                    if (silent != SILENT_OFF){
                        if (silent == SILENT_ANI) {
                            printf("%c\b", anichar[silentani%=MAXANI]);
                            silentani++;
                        }
                        goto out_fflush; /* no other output to stdout */
                    }

                    printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");

                    switch (timestamp) {

                    case 'a': /* absolute with timestamp */
                        printf("(%010ld.%06ld) ", tv.tv_sec, tv.tv_usec);
                        break;

                    case 'A': /* absolute with date */
                    {
                        struct tm tm;
                        char timestring[25];

                        tm = *localtime(&tv.tv_sec);
                        strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
                        printf("(%s.%06ld) ", timestring, tv.tv_usec);
                    }
                    break;

                    case 'd': /* delta */
                    case 'z': /* starting with zero */
                    {
                        struct timeval diff;

                        if (last_tv.tv_sec == 0)   /* first init */
                            last_tv = tv;
                        diff.tv_sec  = tv.tv_sec  - last_tv.tv_sec;
                        diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
                        if (diff.tv_usec < 0)
                            diff.tv_sec--, diff.tv_usec += 1000000;
                        if (diff.tv_sec < 0)
                            diff.tv_sec = diff.tv_usec = 0;
                        printf("(%03ld.%06ld) ", diff.tv_sec, diff.tv_usec);

                        if (timestamp == 'd')
                            last_tv = tv; /* update for delta calculation */
                    }
                    break;

                    default: /* no timestamp output */
                        break;
                    }

                    printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:"");
                    printf("%*s", max_devname_len, devname[idx]);

                    if (extra_msg_info) {

                        if (msg.msg_flags & MSG_DONTROUTE)
                            printf ("  TX %s", extra_m_info[frame.flags & 3]);
                        else
                            printf ("  RX %s", extra_m_info[frame.flags & 3]);
                    }

                    printf("%s  ", (color==1)?col_off:"");

                    fprint_long_canframe(stdout, &frame, NULL, view, maxdlen);

                    printf("%s", (color>1)?col_off:"");
                    printf("\n");
                }

            out_fflush:
                fflush(stdout);
            }
            countc = countc +1;
        }   
    }


    for (i=0; i<currmax; i++)
        close(s[i]);

    if (bridge)
        close(bridge);

    if (log)
        fclose(logfile);

    return 0;
}

实际上,所有重要的事情都在while(running)块中起作用。在此块中,当我将bytes_read = read(fd,&read_buffer,42);作为注释时,它什么也没写,但也没有给出Segmentation Fault错误。当我将GPS的TX引脚连接到BBB时,也会发生同样的情况。因此,当数据来自GPS并由BBB读取时,就会开始出现问题。

Segmentation Fault Err

我该怎么办?

谢谢。

1 个答案:

答案 0 :(得分:0)

您的GPS读取代码

char new_read[38];
char curr_read[33];

strcpy(curr_read, new_read);

正在将38个字符的缓冲区复制到33个字符的缓冲区中,这可能会导致不良后果。

Strcpy会将源缓冲区的内容复制到目标缓冲区,直到它从源缓冲区读取NULL。如果NULL字符位于new_read的第36位,则strcpy将在随机存储器中写入,这可能会导致分段错误。

我猜想,当您以独立方式运行GPS读取代码时,写入随机存储器的操作不会引起注意,但是将其与CAN总线读取结合使用时,它将写入分配的空间,并且会发生错误。

相关问题