不使用cancle线程时需要等待很长时间才能退出两个线程
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include "signal.h" #include <pthread.h> #include <sys/select.h> #include <sys/stat.h> #include <linux/serial.h> #include <sys/ioctl.h> #define SERIAL1 "/dev/ttySTM1" /// dev/ttySTM0对应打印串口终端 #define SERIAL2 "/dev/ttySTM2" #define SERIAL3 "/dev/ttySTM3" #define PRONUM 16 // 串口使用协议的总数量 unsigned char gprotocolType[3][PRONUM]; unsigned char tempbits[3], tempstopbits[3], tempparity[3]; unsigned int tempbaud[3]; // 默认波特率为19200 int g_Sys_Status = 0; int gSerialFd1; int Serial_Cfg(unsigned char num, int baudrate, unsigned char parity, unsigned char data_bit, unsigned char stop_bit) { int fd; speed_t speed; struct termios tios; char device[20]; if (num == 1) { strcpy(device, SERIAL1); } else if (num == 2) { strcpy(device, SERIAL2); } fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK); // mylog(" fd= %d num=%d baud=%d databit=%d stop_bit=%d parity=%c\n",fd,num,baudrate,data_bit,stop_bit,parity); if (fd < 0) { printf("open error\n"); return -1; } #if 1 memset(&tios, 0, sizeof(struct termios)); #else struct termios old_tios; tcgetattr(fd, &old_tios); memcpy(&tios, &old_tios, sizeof(struct termios)); #endif switch (baudrate) { case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; case 230400: speed = B230400; break; case 460800: speed = B460800; break; case 500000: speed = B500000; break; case 576000: speed = B576000; break; case 921600: speed = B921600; break; case 1000000: speed = B1000000; break; case 1152000: speed = B1152000; break; default: speed = B9600; printf("error baudrate\n"); } if ((cfsetispeed(&tios, speed) < 0) || (cfsetospeed(&tios, speed) < 0)) { close(fd); return -1; } tios.c_cflag |= (CREAD | CLOCAL); tios.c_cflag &= ~CSIZE; switch (data_bit) { case 5: tios.c_cflag |= CS5; break; case 6: tios.c_cflag |= CS6; break; case 7: tios.c_cflag |= CS7; break; case 8: default: tios.c_cflag |= CS8; break; } if (stop_bit == 1) tios.c_cflag &= ~CSTOPB; else tios.c_cflag |= CSTOPB; if (parity == 'N') { tios.c_cflag &= ~PARENB; } else if (parity == 'E') { tios.c_cflag |= PARENB; tios.c_cflag &= ~PARODD; } else { tios.c_cflag |= PARENB; tios.c_cflag |= PARODD; } tios.c_cflag &= ~HUPCL; tios.c_iflag &= ~INPCK; tios.c_iflag |= IGNBRK; tios.c_iflag &= ~ICRNL; tios.c_iflag &= ~IXON; tios.c_lflag &= ~IEXTEN; tios.c_lflag &= ~ECHOK; tios.c_lflag &= ~ECHOCTL; tios.c_lflag &= ~ECHOKE; tios.c_oflag &= ~ONLCR; tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); if (parity == 'N') { /* None */ tios.c_iflag &= ~INPCK; } else { tios.c_iflag |= INPCK; } tios.c_iflag &= ~(IXON | IXOFF | IXANY); tios.c_oflag &= ~OPOST; tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = 0; if (tcsetattr(fd, TCSANOW, &tios) < 0) { close(fd); return -1; } struct serial_rs485 rs485conf; ioctl(fd, TIOCGRS485, &rs485conf); rs485conf.flags |= SER_RS485_ENABLED; ioctl(fd, TIOCSRS485, &rs485conf); return fd; } void RTU_receive() { int fd; fd = gSerialFd1; fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); struct timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; while (1) { // printf("======================================\n"); int ret = select(fd + 1, &fds, NULL, NULL, &tv); if (ret == -1) { fprintf(stderr, "fail to select, error: %d, %s\n", errno, strerror(errno)); } else if (ret == 0) { fprintf(stderr, "select timeout\n"); } else { fprintf(stdout, "success to select\n"); // int result =read(); } if (g_Sys_Status == 4) { printf("===============\n"); break; } else { printf("===============g_Sys_Status == 2\n"); } } } void main() // int argc, int *argv { int i; int ret[PRONUM]; pthread_attr_t thread_attr; pthread_t thread_id; // struct sched_param thread_param[PRONUM]; unsigned char myNum[PRONUM]; int tempEnable[PRONUM]; if (1) { gSerialFd1 = Serial_Cfg(1, 19200, 'E', 8, 1); pthread_attr_init(&thread_attr); // thread_param[0].sched_priority = RUNNETWORK_THREAD_PRIO; // pthread_attr_setschedpolicy(&(thread_attr[0]), SCHED_FIFO); // pthread_attr_setschedparam(&(thread_attr[0]), &(thread_param[0])); ret[0] = pthread_create(&(thread_id), &(thread_attr), (void *)RTU_receive, NULL); if (ret[0] != 0) { printf("pthread_create error thread_param!\n"); // continue; } pthread_attr_destroy(&(thread_attr)); } char cmdbuf[20] = {0}; char *string; while (1) { printf("2input cmd:"); memset(cmdbuf, 0, 20 * sizeof(char)); string = fgets(cmdbuf, 20, stdin); // if (strcmp(cmdbuf, "2\n") == 0) { g_Sys_Status = 2; } else if (strcmp(cmdbuf, "4\n") == 0) { g_Sys_Status = 4; } else if (strcmp(cmdbuf, "6\n") == 0) { printf("RRRRRR= 6\n"); } printf("%s\n", string); if (g_Sys_Status == 4) // 停止状态下结束所有线程 { // pthread_cancel(thread_id); //使用cancle时快速退出线程 pthread_join(thread_id, NULL); break; } usleep(5000); } }
问题2:为何select一次之后就不能再次循环,再次进入select?
需要将tv时间再次赋值
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include "signal.h" #include <pthread.h> #include <sys/select.h> #include <sys/stat.h> #include <linux/serial.h> #include <sys/ioctl.h> #define SERIAL1 "/dev/ttySTM1" /// dev/ttySTM0对应打印串口终端 #define SERIAL2 "/dev/ttySTM2" #define SERIAL3 "/dev/ttySTM3" #define PRONUM 16 // 串口使用协议的总数量 unsigned char gprotocolType[3][PRONUM]; unsigned char tempbits[3], tempstopbits[3], tempparity[3]; unsigned int tempbaud[3]; // 默认波特率为19200 int g_Sys_Status = 0; int gSerialFd1; int Serial_Cfg(unsigned char num, int baudrate, unsigned char parity, unsigned char data_bit, unsigned char stop_bit) { int fd; speed_t speed; struct termios tios; char device[20]; if (num == 1) { strcpy(device, SERIAL1); } else if (num == 2) { strcpy(device, SERIAL2); } fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK); // mylog(" fd= %d num=%d baud=%d databit=%d stop_bit=%d parity=%c\n",fd,num,baudrate,data_bit,stop_bit,parity); if (fd < 0) { printf("open error\n"); return -1; } #if 1 memset(&tios, 0, sizeof(struct termios)); #else struct termios old_tios; tcgetattr(fd, &old_tios); memcpy(&tios, &old_tios, sizeof(struct termios)); #endif switch (baudrate) { case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; case 230400: speed = B230400; break; case 460800: speed = B460800; break; case 500000: speed = B500000; break; case 576000: speed = B576000; break; case 921600: speed = B921600; break; case 1000000: speed = B1000000; break; case 1152000: speed = B1152000; break; default: speed = B9600; printf("error baudrate\n"); } if ((cfsetispeed(&tios, speed) < 0) || (cfsetospeed(&tios, speed) < 0)) { close(fd); return -1; } tios.c_cflag |= (CREAD | CLOCAL); tios.c_cflag &= ~CSIZE; switch (data_bit) { case 5: tios.c_cflag |= CS5; break; case 6: tios.c_cflag |= CS6; break; case 7: tios.c_cflag |= CS7; break; case 8: default: tios.c_cflag |= CS8; break; } if (stop_bit == 1) tios.c_cflag &= ~CSTOPB; else tios.c_cflag |= CSTOPB; if (parity == 'N') { tios.c_cflag &= ~PARENB; } else if (parity == 'E') { tios.c_cflag |= PARENB; tios.c_cflag &= ~PARODD; } else { tios.c_cflag |= PARENB; tios.c_cflag |= PARODD; } tios.c_cflag &= ~HUPCL; tios.c_iflag &= ~INPCK; tios.c_iflag |= IGNBRK; tios.c_iflag &= ~ICRNL; tios.c_iflag &= ~IXON; tios.c_lflag &= ~IEXTEN; tios.c_lflag &= ~ECHOK; tios.c_lflag &= ~ECHOCTL; tios.c_lflag &= ~ECHOKE; tios.c_oflag &= ~ONLCR; tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); if (parity == 'N') { /* None */ tios.c_iflag &= ~INPCK; } else { tios.c_iflag |= INPCK; } tios.c_iflag &= ~(IXON | IXOFF | IXANY); tios.c_oflag &= ~OPOST; tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = 0; if (tcsetattr(fd, TCSANOW, &tios) < 0) { close(fd); return -1; } struct serial_rs485 rs485conf; ioctl(fd, TIOCGRS485, &rs485conf); rs485conf.flags |= SER_RS485_ENABLED; ioctl(fd, TIOCSRS485, &rs485conf); return fd; } void RTU_receive() { int fd; fd = gSerialFd1; fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); struct timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; while (1) { tv.tv_sec = 3; tv.tv_usec = 0; // printf("======================================\n"); int ret = select(fd + 1, &fds, NULL, NULL, &tv); if (ret == -1) { fprintf(stderr, "fail to select, error: %d, %s\n", errno, strerror(errno)); } else if (ret == 0) { fprintf(stderr, "select timeout\n"); } else { fprintf(stdout, "success to select\n"); // int result =read(); } if (g_Sys_Status == 4) { printf("===============\n"); break; } else { printf("===============g_Sys_Status == 2\n"); } } } void main() // int argc, int *argv { int i; int ret[PRONUM]; pthread_attr_t thread_attr; pthread_t thread_id; // struct sched_param thread_param[PRONUM]; unsigned char myNum[PRONUM]; int tempEnable[PRONUM]; if (1) { gSerialFd1 = Serial_Cfg(1, 19200, 'E', 8, 1); pthread_attr_init(&thread_attr); // thread_param[0].sched_priority = RUNNETWORK_THREAD_PRIO; // pthread_attr_setschedpolicy(&(thread_attr[0]), SCHED_FIFO); // pthread_attr_setschedparam(&(thread_attr[0]), &(thread_param[0])); ret[0] = pthread_create(&(thread_id), &(thread_attr), (void *)RTU_receive, NULL); if (ret[0] != 0) { printf("pthread_create error thread_param!\n"); // continue; } pthread_attr_destroy(&(thread_attr)); } char cmdbuf[20] = {0}; char *string; while (1) { printf("2input cmd:"); memset(cmdbuf, 0, 20 * sizeof(char)); string = fgets(cmdbuf, 20, stdin); // if (strcmp(cmdbuf, "2\n") == 0) { g_Sys_Status = 2; } else if (strcmp(cmdbuf, "4\n") == 0) { g_Sys_Status = 4; } else if (strcmp(cmdbuf, "6\n") == 0) { printf("RRRRRR= 6\n"); } printf("%s\n", string); if (g_Sys_Status == 4) // 停止状态下结束所有线程 { pthread_cancel(thread_id); pthread_join(thread_id, NULL); break; } usleep(5000); } }