串行设备读取功能中的段错误
SegFault in read function for serial device
我正在尝试通过串口连接测量设备。我已经创建了一个成功的程序,它可以运行并执行我想要的操作,但它没有实时用户输入。
我的问题来自我正在创建的程序,我想在其中制作一个实时串行终端与设备进行交互。在这个程序中,我让用户向机器键入命令,对于某些命令,机器必须 return a 1 或 0。这就是问题所在。在实时环境中,当我在命令后读取 1 时出现段错误。
这是处理要求机器发送 1 或 0 的命令的段。
buf = malloc(1);
if (buf == NULL)
{
perror("memory error");
goto fail;
}
...
if (write == 0)
{
for (i = 0; i < read_com.num; i++)
{
if (strcmp(buff, read_com.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
这是发生段错误的读取端口函数
int read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size)
{
r = read(fd, buf + received, size - received);
if (r < 0)
{
perror("failed to read from port");
return -1;
}
if (r == 0)
{
break;
}
received += r;
}
return received;
}
以下所有代码:
live.c:
#include "GPIB_prof.h"
#include "serial.h"
#include "commands.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
const struct com read_com = {3, {"OPC?;PRES;\r", "OPC?;WAIT;\r", "CORRON;\r"}};
const struct com numc = {3, {"STAR", "STOP", "POIN"}};
int main(int argc, char *argv[])
{
int fd;
int ret;
char *buff;
char *buf;
int i;
bool write = 0;
int fin = 0;
char *numb;
char *rem;
int star;
int stop;
int poin;
char *dat;
int fc = 0;
char *file;
FILE *temp;
FILE *f;
rem = malloc(256);
if (rem == NULL)
{
perror("memory error");
goto fail;
}
numb = malloc(4);
if (numb == NULL)
{
perror("memory error");
goto fail;
}
buff = malloc(256);
if (buff == NULL)
{
perror("memory error");
goto fail;
}
buf = malloc(1);
if (buf == NULL)
{
perror("memory error");
goto fail;
}
file = malloc(5);
if (file == NULL)
{
perror("memory error");
goto fail;
}
if (argc < 3)
{
printf("Usage: %s [serial device] [baud rate]", argv[0]);
goto fail;
}
fd = open_port(argv[1], atoi(argv[2]));
if (fd < 0)
goto fail;
ret = GPIB_conf(fd, 0);
if (ret < 0)
goto fail;
while (fin == 0)
{
write = 0;
scanf("%s", buff);
strcat(buff, "\r");
//if (ret<0) goto fail;
for (i = 0; i < strlen(buff); i++)
{
if (i < 4)
{
numb[i] = buff[i];
}
else
{
rem[i - 4] = buff[i];
}
}
if (strcmp(numb, "OUTP") == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
ret = read_port(fd, dat, 50 * poin);
if (ret < 0)
goto fail;
else
goto data;
}
if (write == 0)
{
for (i = 0; i < read_com.num; i++)
{
if (strcmp(buff, read_com.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
if (write == 0)
{
for (i = 0; i < numc.num; i++)
{
if (strcmp(numb, numc.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
if (strcmp(numb, "STAR") == 0)
{
star = atoi(rem);
}
else if (strcmp(numb, "STOP") == 0)
{
stop = atoi(rem);
}
else if (strcmp(numb, "POIN") == 0)
{
poin = atoi(rem);
dat = malloc(50 * poin);
if (dat == NULL)
{
perror("memory error");
goto fail;
}
fc++;
}
break;
}
}
if (write == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
}
}
}
printf("Start freq: %d\nStop freq: %d\n", star, stop);
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return 0;
data:
ret = sprintf(file, "data%d", fc);
if (ret < 0)
goto fail;
temp = fopen(file, "w+");
if (temp == NULL)
{
perror("failed to open file");
fclose(temp);
goto fail;
}
fclose(temp);
ret = remove(file);
if (ret != 0)
{
perror("failed to remove file");
goto fail;
}
f = fopen(file, "w");
if (f == NULL)
{
perror("failed to open file");
fclose(f);
goto fail;
}
for (i = 0; i < (50 * poin); i++)
{
ret = fprintf(f, "%c", dat[i]);
if (ret < 0)
{
fclose(f);
goto fail;
}
}
fclose(f);
fin++;
fail:
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return -1;
}
serial.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <stdint.h>
#include <unistd.h>
#include "serial.h"
#include "GPIB_prof.h"
struct termios options;
int open_port(const char *dev, uint32_t baud)
{
int fd;
int ret;
char *baud_f;
struct termios opt;
baud_f = malloc(8 * sizeof(char));
if (baud_f == NULL)
{
perror("memory error");
goto fail;
}
fd = open(dev, O_RDWR, 0777);
if (fd < 0)
{
perror(dev);
goto fail;
}
ret = tcflush(fd, TCIOFLUSH);
if (ret)
{
perror("tcgetattr failed");
goto fail;
}
opt.c_cflag = (opt.c_cflag & ~CSIZE) | CS8;
opt.c_cflag &= ~IGNBRK;
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 5;
opt.c_cc[VMIN] = 1;
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= 0;
opt.c_cflag &= ~CSTOPB;
ret = sprintf(baud_f, "B%d", baud);
if (ret < 0)
{
perror("memory error");
goto fail;
}
baud = (uintptr_t)baud_f;
cfsetospeed(&opt, baud);
cfsetispeed(&opt, baud);
ret = tcsetattr(fd, TCSANOW, &opt);
if (ret)
{
perror("tcsetarre failed");
goto fail;
}
free(baud_f);
return fd;
fail:
free(baud_f);
close(fd);
return -1;
}
int read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size)
{
r = read(fd, buf + received, size - received);
if (r < 0)
{
perror("failed to read from port");
return -1;
}
if (r == 0)
{
break;
}
received += r;
}
return received;
}
int write_port(int fd, const char *buf, const size_t size)
{
ssize_t res;
res = write(fd, buf, size);
if (res != (ssize_t)size)
{
perror("failed to write to port");
return -1;
}
usleep(size * 100);
return 0;
}
int GPIB_conf(int fd, int profile)
{
int ret;
switch (profile)
{
case 0:
ret = def(fd);
if (ret < 0)
goto fail;
}
return 0;
fail:
return -1;
}
serial.h
#ifndef _SERIAL_H_
#define _SERIAL_H_
#include <stdint.h>
#include <stddef.h>
#include "GPIB_prof.h"
int open_port (const char *dev, uint32_t baud);
int read_port (int fd, char *buf, size_t size);
int write_port (int fd, const char *buf, size_t size);
int GPIB_conf (int fd, int profile);
#endif
commands.h:
#ifndef _COMMANDS_H_
#define _COMMANDS_H_
struct com
{
const int num;
const char *check[];
};
#endif
GPIB_prof.c:
#include "GPIB_prof.h"
#include "serial.h"
int def(int fd)
{
int ret;
ret = write_port(fd, "++mode 1\r", 9);
if (ret < 0)
goto fail;
ret = write_port(fd, "++addr 16\r", 10);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eoi 0\r", 8);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eot_enable 1\r", 15);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eot_char 13\r", 14);
if (ret < 0)
goto fail;
ret = write_port(fd, "++ifc\r", 6);
if (ret < 0)
goto fail;
ret = write_port(fd, "++auto 1\r", 9);
if (ret < 0)
goto fail;
return 0;
fail:
return -1;
}
GPIB_prof.h:
#ifndef _PROFILE_H_
#define _PROFILE_H_
int def(int fd);
#endif
警告:这可能不是一个完整的解决方案,因为有许多编译器警告可能未初始化的变量等
请注意,我会重命名一些变量。您有一个名为 read
的全局变量。这往往与标准 read
函数冲突。 (即)不要定义与标准 functions/variables 冲突的 functions/variables:买者自负。
这是我为(例如)cc -o orig orig.c -Wall -Wextra -O2
.
获得的编译器输出
值得注意的是,许多 pointer 变量可能具有未初始化的值。这确实应该重组并修复警告,因为代码很脆弱,编译器会指出可以轻松解释运行时错误的事情。
orig.c: In function ‘GPIB_conf’:
orig.c:136:15: warning: unused parameter ‘fd’ [-Wunused-parameter]
GPIB_conf(int fd, int profile)
~~~~^~
orig.c: In function ‘main’:
orig.c:217:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
for (i = 0; i < strlen(buff); i++) {
^
orig.c:325:5: warning: increment of a boolean expression [-Wbool-operation]
fin++;
^~
orig.c: In function ‘open_port’:
orig.c:96:2: warning: ‘fd’ may be used uninitialized in this function [-Wmaybe-uninitialized]
close(fd);
^~~~~~~~~
orig.c: In function ‘main’:
orig.c:295:27: warning: ‘%d’ directive writing between 1 and 10 bytes into a region of size 1 [-Wformat-overflow=]
ret = sprintf(file, "data%d", fc);
^~
orig.c:295:22: note: directive argument in the range [0, 2147483647]
ret = sprintf(file, "data%d", fc);
^~~~~~~~
orig.c:295:8: note: ‘sprintf’ output between 6 and 15 bytes into a destination of size 5
ret = sprintf(file, "data%d", fc);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
orig.c:332:2: warning: ‘file’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(file);
^~~~~~~~~~
orig.c:333:2: warning: ‘dat’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(dat);
^~~~~~~~~
orig.c:329:2: warning: ‘numb’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(numb);
^~~~~~~~~~
orig.c:331:2: warning: ‘buf’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(buf);
^~~~~~~~~
orig.c:330:2: warning: ‘buff’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(buff);
^~~~~~~~~~
orig.c:230:32: warning: ‘poin’ may be used uninitialized in this function [-Wmaybe-uninitialized]
ret = read_port(fd, dat, 50 * poin);
~~~^~~~~~
我必须 refactor/nop 一些代码才能在 [missing] .h
文件中没有完整定义的情况下进行编译。但是,这些技巧不会解释上述警告。
#include "GPIB_prof.h"
#include "serial.h"
#include "commands.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define def(_fd) \
0
struct com {
int num;
char *check[3];
};
const struct com read_com = { 3, {"OPC?;PRES;\r", "OPC?;WAIT;\r", "CORRON;\r"} };
const struct com numc = { 3, {"STAR", "STOP", "POIN"} };
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <stdint.h>
#include <unistd.h>
#include "serial.h"
#include "GPIB_prof.h"
struct termios options;
int
open_port(const char *dev, uint32_t baud)
{
int fd;
int ret;
char *baud_f;
struct termios opt;
baud_f = malloc(8 * sizeof(char));
if (baud_f == NULL) {
perror("memory error");
goto fail;
}
fd = open(dev, O_RDWR, 0777);
if (fd < 0) {
perror(dev);
goto fail;
}
ret = tcflush(fd, TCIOFLUSH);
if (ret) {
perror("tcgetattr failed");
goto fail;
}
opt.c_cflag = (opt.c_cflag & ~CSIZE) | CS8;
opt.c_cflag &= ~IGNBRK;
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 5;
opt.c_cc[VMIN] = 1;
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= 0;
opt.c_cflag &= ~CSTOPB;
ret = sprintf(baud_f, "B%d", baud);
if (ret < 0) {
perror("memory error");
goto fail;
}
baud = (uintptr_t) baud_f;
cfsetospeed(&opt, baud);
cfsetispeed(&opt, baud);
ret = tcsetattr(fd, TCSANOW, &opt);
if (ret) {
perror("tcsetarre failed");
goto fail;
}
free(baud_f);
return fd;
fail:
free(baud_f);
close(fd);
return -1;
}
int
read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size) {
r = read(fd, buf + received, size - received);
if (r < 0) {
perror("failed to read from port");
return -1;
}
if (r == 0) {
break;
}
received += r;
}
return received;
}
int
write_port(int fd, const char *buf, const size_t size)
{
ssize_t res;
res = write(fd, buf, size);
if (res != (ssize_t) size) {
perror("failed to write to port");
return -1;
}
usleep(size * 100);
return 0;
}
int
GPIB_conf(int fd, int profile)
{
int ret;
switch (profile) {
case 0:
ret = def(fd);
if (ret < 0)
goto fail;
}
return 0;
fail:
return -1;
}
int
main(int argc, char *argv[])
{
int fd;
int ret;
char *buff;
char *buf;
int i;
bool write = 0;
bool fin = 0;
char *numb;
char *rem;
int star;
int stop;
int poin;
char *dat;
int fc = 0;
char *file;
FILE *temp;
FILE *f;
rem = malloc(256);
if (rem == NULL) {
perror("memory error");
goto fail;
}
numb = malloc(4);
if (numb == NULL) {
perror("memory error");
goto fail;
}
buff = malloc(256);
if (buff == NULL) {
perror("memory error");
goto fail;
}
buf = malloc(1);
if (buf == NULL) {
perror("memory error");
goto fail;
}
file = malloc(5);
if (file == NULL) {
perror("memory error");
goto fail;
}
if (argc < 3) {
printf("Usage: %s [serial device] [baud rate]", argv[0]);
goto fail;
}
fd = open_port(argv[1], atoi(argv[2]));
if (fd < 0)
goto fail;
ret = GPIB_conf(fd, 0);
if (ret < 0)
goto fail;
while (fin == 0) {
write = 0;
scanf("%s", buff);
strcat(buff, "\r");
// if (ret<0) goto fail;
for (i = 0; i < strlen(buff); i++) {
if (i < 4) {
numb[i] = buff[i];
}
else {
rem[i - 4] = buff[i];
}
}
if (strcmp(numb, "OUTP") == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
ret = read_port(fd, dat, 50 * poin);
if (ret < 0)
goto fail;
else
goto data;
}
if (write == 0) {
for (i = 0; i < read_com.num; i++) {
if (strcmp(buff, read_com.check[i]) == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
if (write == 0) {
for (i = 0; i < numc.num; i++) {
if (strcmp(numb, numc.check[i]) == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
if (strcmp(numb, "STAR") == 0) {
star = atoi(rem);
}
else if (strcmp(numb, "STOP") == 0) {
stop = atoi(rem);
}
else if (strcmp(numb, "POIN") == 0) {
poin = atoi(rem);
dat = malloc(50 * poin);
if (dat == NULL) {
perror("memory error");
goto fail;
}
fc++;
}
break;
}
}
if (write == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
}
}
}
printf("Start freq: %d\nStop freq: %d\n", star, stop);
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return 0;
data:
ret = sprintf(file, "data%d", fc);
if (ret < 0)
goto fail;
temp = fopen(file, "w+");
if (temp == NULL) {
perror("failed to open file");
fclose(temp);
goto fail;
}
fclose(temp);
ret = remove(file);
if (ret != 0) {
perror("failed to remove file");
goto fail;
}
f = fopen(file, "w");
if (f == NULL) {
perror("failed to open file");
fclose(f);
goto fail;
}
for (i = 0; i < (50 * poin); i++) {
ret = fprintf(f, "%c", dat[i]);
if (ret < 0) {
fclose(f);
goto fail;
}
}
fclose(f);
fin++;
fail:
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return -1;
}
我正在尝试通过串口连接测量设备。我已经创建了一个成功的程序,它可以运行并执行我想要的操作,但它没有实时用户输入。 我的问题来自我正在创建的程序,我想在其中制作一个实时串行终端与设备进行交互。在这个程序中,我让用户向机器键入命令,对于某些命令,机器必须 return a 1 或 0。这就是问题所在。在实时环境中,当我在命令后读取 1 时出现段错误。
这是处理要求机器发送 1 或 0 的命令的段。
buf = malloc(1);
if (buf == NULL)
{
perror("memory error");
goto fail;
}
...
if (write == 0)
{
for (i = 0; i < read_com.num; i++)
{
if (strcmp(buff, read_com.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
这是发生段错误的读取端口函数
int read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size)
{
r = read(fd, buf + received, size - received);
if (r < 0)
{
perror("failed to read from port");
return -1;
}
if (r == 0)
{
break;
}
received += r;
}
return received;
}
以下所有代码:
live.c:
#include "GPIB_prof.h"
#include "serial.h"
#include "commands.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
const struct com read_com = {3, {"OPC?;PRES;\r", "OPC?;WAIT;\r", "CORRON;\r"}};
const struct com numc = {3, {"STAR", "STOP", "POIN"}};
int main(int argc, char *argv[])
{
int fd;
int ret;
char *buff;
char *buf;
int i;
bool write = 0;
int fin = 0;
char *numb;
char *rem;
int star;
int stop;
int poin;
char *dat;
int fc = 0;
char *file;
FILE *temp;
FILE *f;
rem = malloc(256);
if (rem == NULL)
{
perror("memory error");
goto fail;
}
numb = malloc(4);
if (numb == NULL)
{
perror("memory error");
goto fail;
}
buff = malloc(256);
if (buff == NULL)
{
perror("memory error");
goto fail;
}
buf = malloc(1);
if (buf == NULL)
{
perror("memory error");
goto fail;
}
file = malloc(5);
if (file == NULL)
{
perror("memory error");
goto fail;
}
if (argc < 3)
{
printf("Usage: %s [serial device] [baud rate]", argv[0]);
goto fail;
}
fd = open_port(argv[1], atoi(argv[2]));
if (fd < 0)
goto fail;
ret = GPIB_conf(fd, 0);
if (ret < 0)
goto fail;
while (fin == 0)
{
write = 0;
scanf("%s", buff);
strcat(buff, "\r");
//if (ret<0) goto fail;
for (i = 0; i < strlen(buff); i++)
{
if (i < 4)
{
numb[i] = buff[i];
}
else
{
rem[i - 4] = buff[i];
}
}
if (strcmp(numb, "OUTP") == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
ret = read_port(fd, dat, 50 * poin);
if (ret < 0)
goto fail;
else
goto data;
}
if (write == 0)
{
for (i = 0; i < read_com.num; i++)
{
if (strcmp(buff, read_com.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
if (write == 0)
{
for (i = 0; i < numc.num; i++)
{
if (strcmp(numb, numc.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
if (strcmp(numb, "STAR") == 0)
{
star = atoi(rem);
}
else if (strcmp(numb, "STOP") == 0)
{
stop = atoi(rem);
}
else if (strcmp(numb, "POIN") == 0)
{
poin = atoi(rem);
dat = malloc(50 * poin);
if (dat == NULL)
{
perror("memory error");
goto fail;
}
fc++;
}
break;
}
}
if (write == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
}
}
}
printf("Start freq: %d\nStop freq: %d\n", star, stop);
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return 0;
data:
ret = sprintf(file, "data%d", fc);
if (ret < 0)
goto fail;
temp = fopen(file, "w+");
if (temp == NULL)
{
perror("failed to open file");
fclose(temp);
goto fail;
}
fclose(temp);
ret = remove(file);
if (ret != 0)
{
perror("failed to remove file");
goto fail;
}
f = fopen(file, "w");
if (f == NULL)
{
perror("failed to open file");
fclose(f);
goto fail;
}
for (i = 0; i < (50 * poin); i++)
{
ret = fprintf(f, "%c", dat[i]);
if (ret < 0)
{
fclose(f);
goto fail;
}
}
fclose(f);
fin++;
fail:
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return -1;
}
serial.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <stdint.h>
#include <unistd.h>
#include "serial.h"
#include "GPIB_prof.h"
struct termios options;
int open_port(const char *dev, uint32_t baud)
{
int fd;
int ret;
char *baud_f;
struct termios opt;
baud_f = malloc(8 * sizeof(char));
if (baud_f == NULL)
{
perror("memory error");
goto fail;
}
fd = open(dev, O_RDWR, 0777);
if (fd < 0)
{
perror(dev);
goto fail;
}
ret = tcflush(fd, TCIOFLUSH);
if (ret)
{
perror("tcgetattr failed");
goto fail;
}
opt.c_cflag = (opt.c_cflag & ~CSIZE) | CS8;
opt.c_cflag &= ~IGNBRK;
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 5;
opt.c_cc[VMIN] = 1;
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= 0;
opt.c_cflag &= ~CSTOPB;
ret = sprintf(baud_f, "B%d", baud);
if (ret < 0)
{
perror("memory error");
goto fail;
}
baud = (uintptr_t)baud_f;
cfsetospeed(&opt, baud);
cfsetispeed(&opt, baud);
ret = tcsetattr(fd, TCSANOW, &opt);
if (ret)
{
perror("tcsetarre failed");
goto fail;
}
free(baud_f);
return fd;
fail:
free(baud_f);
close(fd);
return -1;
}
int read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size)
{
r = read(fd, buf + received, size - received);
if (r < 0)
{
perror("failed to read from port");
return -1;
}
if (r == 0)
{
break;
}
received += r;
}
return received;
}
int write_port(int fd, const char *buf, const size_t size)
{
ssize_t res;
res = write(fd, buf, size);
if (res != (ssize_t)size)
{
perror("failed to write to port");
return -1;
}
usleep(size * 100);
return 0;
}
int GPIB_conf(int fd, int profile)
{
int ret;
switch (profile)
{
case 0:
ret = def(fd);
if (ret < 0)
goto fail;
}
return 0;
fail:
return -1;
}
serial.h
#ifndef _SERIAL_H_
#define _SERIAL_H_
#include <stdint.h>
#include <stddef.h>
#include "GPIB_prof.h"
int open_port (const char *dev, uint32_t baud);
int read_port (int fd, char *buf, size_t size);
int write_port (int fd, const char *buf, size_t size);
int GPIB_conf (int fd, int profile);
#endif
commands.h:
#ifndef _COMMANDS_H_
#define _COMMANDS_H_
struct com
{
const int num;
const char *check[];
};
#endif
GPIB_prof.c:
#include "GPIB_prof.h"
#include "serial.h"
int def(int fd)
{
int ret;
ret = write_port(fd, "++mode 1\r", 9);
if (ret < 0)
goto fail;
ret = write_port(fd, "++addr 16\r", 10);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eoi 0\r", 8);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eot_enable 1\r", 15);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eot_char 13\r", 14);
if (ret < 0)
goto fail;
ret = write_port(fd, "++ifc\r", 6);
if (ret < 0)
goto fail;
ret = write_port(fd, "++auto 1\r", 9);
if (ret < 0)
goto fail;
return 0;
fail:
return -1;
}
GPIB_prof.h:
#ifndef _PROFILE_H_
#define _PROFILE_H_
int def(int fd);
#endif
警告:这可能不是一个完整的解决方案,因为有许多编译器警告可能未初始化的变量等
请注意,我会重命名一些变量。您有一个名为 read
的全局变量。这往往与标准 read
函数冲突。 (即)不要定义与标准 functions/variables 冲突的 functions/variables:买者自负。
这是我为(例如)cc -o orig orig.c -Wall -Wextra -O2
.
值得注意的是,许多 pointer 变量可能具有未初始化的值。这确实应该重组并修复警告,因为代码很脆弱,编译器会指出可以轻松解释运行时错误的事情。
orig.c: In function ‘GPIB_conf’:
orig.c:136:15: warning: unused parameter ‘fd’ [-Wunused-parameter]
GPIB_conf(int fd, int profile)
~~~~^~
orig.c: In function ‘main’:
orig.c:217:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
for (i = 0; i < strlen(buff); i++) {
^
orig.c:325:5: warning: increment of a boolean expression [-Wbool-operation]
fin++;
^~
orig.c: In function ‘open_port’:
orig.c:96:2: warning: ‘fd’ may be used uninitialized in this function [-Wmaybe-uninitialized]
close(fd);
^~~~~~~~~
orig.c: In function ‘main’:
orig.c:295:27: warning: ‘%d’ directive writing between 1 and 10 bytes into a region of size 1 [-Wformat-overflow=]
ret = sprintf(file, "data%d", fc);
^~
orig.c:295:22: note: directive argument in the range [0, 2147483647]
ret = sprintf(file, "data%d", fc);
^~~~~~~~
orig.c:295:8: note: ‘sprintf’ output between 6 and 15 bytes into a destination of size 5
ret = sprintf(file, "data%d", fc);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
orig.c:332:2: warning: ‘file’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(file);
^~~~~~~~~~
orig.c:333:2: warning: ‘dat’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(dat);
^~~~~~~~~
orig.c:329:2: warning: ‘numb’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(numb);
^~~~~~~~~~
orig.c:331:2: warning: ‘buf’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(buf);
^~~~~~~~~
orig.c:330:2: warning: ‘buff’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(buff);
^~~~~~~~~~
orig.c:230:32: warning: ‘poin’ may be used uninitialized in this function [-Wmaybe-uninitialized]
ret = read_port(fd, dat, 50 * poin);
~~~^~~~~~
我必须 refactor/nop 一些代码才能在 [missing] .h
文件中没有完整定义的情况下进行编译。但是,这些技巧不会解释上述警告。
#include "GPIB_prof.h"
#include "serial.h"
#include "commands.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define def(_fd) \
0
struct com {
int num;
char *check[3];
};
const struct com read_com = { 3, {"OPC?;PRES;\r", "OPC?;WAIT;\r", "CORRON;\r"} };
const struct com numc = { 3, {"STAR", "STOP", "POIN"} };
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <stdint.h>
#include <unistd.h>
#include "serial.h"
#include "GPIB_prof.h"
struct termios options;
int
open_port(const char *dev, uint32_t baud)
{
int fd;
int ret;
char *baud_f;
struct termios opt;
baud_f = malloc(8 * sizeof(char));
if (baud_f == NULL) {
perror("memory error");
goto fail;
}
fd = open(dev, O_RDWR, 0777);
if (fd < 0) {
perror(dev);
goto fail;
}
ret = tcflush(fd, TCIOFLUSH);
if (ret) {
perror("tcgetattr failed");
goto fail;
}
opt.c_cflag = (opt.c_cflag & ~CSIZE) | CS8;
opt.c_cflag &= ~IGNBRK;
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 5;
opt.c_cc[VMIN] = 1;
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= 0;
opt.c_cflag &= ~CSTOPB;
ret = sprintf(baud_f, "B%d", baud);
if (ret < 0) {
perror("memory error");
goto fail;
}
baud = (uintptr_t) baud_f;
cfsetospeed(&opt, baud);
cfsetispeed(&opt, baud);
ret = tcsetattr(fd, TCSANOW, &opt);
if (ret) {
perror("tcsetarre failed");
goto fail;
}
free(baud_f);
return fd;
fail:
free(baud_f);
close(fd);
return -1;
}
int
read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size) {
r = read(fd, buf + received, size - received);
if (r < 0) {
perror("failed to read from port");
return -1;
}
if (r == 0) {
break;
}
received += r;
}
return received;
}
int
write_port(int fd, const char *buf, const size_t size)
{
ssize_t res;
res = write(fd, buf, size);
if (res != (ssize_t) size) {
perror("failed to write to port");
return -1;
}
usleep(size * 100);
return 0;
}
int
GPIB_conf(int fd, int profile)
{
int ret;
switch (profile) {
case 0:
ret = def(fd);
if (ret < 0)
goto fail;
}
return 0;
fail:
return -1;
}
int
main(int argc, char *argv[])
{
int fd;
int ret;
char *buff;
char *buf;
int i;
bool write = 0;
bool fin = 0;
char *numb;
char *rem;
int star;
int stop;
int poin;
char *dat;
int fc = 0;
char *file;
FILE *temp;
FILE *f;
rem = malloc(256);
if (rem == NULL) {
perror("memory error");
goto fail;
}
numb = malloc(4);
if (numb == NULL) {
perror("memory error");
goto fail;
}
buff = malloc(256);
if (buff == NULL) {
perror("memory error");
goto fail;
}
buf = malloc(1);
if (buf == NULL) {
perror("memory error");
goto fail;
}
file = malloc(5);
if (file == NULL) {
perror("memory error");
goto fail;
}
if (argc < 3) {
printf("Usage: %s [serial device] [baud rate]", argv[0]);
goto fail;
}
fd = open_port(argv[1], atoi(argv[2]));
if (fd < 0)
goto fail;
ret = GPIB_conf(fd, 0);
if (ret < 0)
goto fail;
while (fin == 0) {
write = 0;
scanf("%s", buff);
strcat(buff, "\r");
// if (ret<0) goto fail;
for (i = 0; i < strlen(buff); i++) {
if (i < 4) {
numb[i] = buff[i];
}
else {
rem[i - 4] = buff[i];
}
}
if (strcmp(numb, "OUTP") == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
ret = read_port(fd, dat, 50 * poin);
if (ret < 0)
goto fail;
else
goto data;
}
if (write == 0) {
for (i = 0; i < read_com.num; i++) {
if (strcmp(buff, read_com.check[i]) == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
if (write == 0) {
for (i = 0; i < numc.num; i++) {
if (strcmp(numb, numc.check[i]) == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
if (strcmp(numb, "STAR") == 0) {
star = atoi(rem);
}
else if (strcmp(numb, "STOP") == 0) {
stop = atoi(rem);
}
else if (strcmp(numb, "POIN") == 0) {
poin = atoi(rem);
dat = malloc(50 * poin);
if (dat == NULL) {
perror("memory error");
goto fail;
}
fc++;
}
break;
}
}
if (write == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
}
}
}
printf("Start freq: %d\nStop freq: %d\n", star, stop);
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return 0;
data:
ret = sprintf(file, "data%d", fc);
if (ret < 0)
goto fail;
temp = fopen(file, "w+");
if (temp == NULL) {
perror("failed to open file");
fclose(temp);
goto fail;
}
fclose(temp);
ret = remove(file);
if (ret != 0) {
perror("failed to remove file");
goto fail;
}
f = fopen(file, "w");
if (f == NULL) {
perror("failed to open file");
fclose(f);
goto fail;
}
for (i = 0; i < (50 * poin); i++) {
ret = fprintf(f, "%c", dat[i]);
if (ret < 0) {
fclose(f);
goto fail;
}
}
fclose(f);
fin++;
fail:
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return -1;
}