C语言读取TTY写入日志程序的设备打开失败与编译警告问题
问题分析与修复方案
1. 编译警告解决
终端编译出现的warning: return type of 'main' is not 'int'是因为C语言标准明确要求main函数的返回类型必须为int,而非void。修改方法:
- 将
void main()改为int main() - 在函数末尾添加
return 0;,符合C标准的返回值规范
2. TTY设备打开失败原因及解决
在线编译器中fd_in=-1的核心原因:
- 无真实TTY设备:在线编译环境多为虚拟化环境,不会提供真实的串口设备
/dev/ttys000,设备本身不存在。 - 权限不足:本地环境中,
/dev/ttys000这类TTY设备通常属于tty用户组,普通用户无访问权限,需通过sudo运行程序,或将当前用户加入tty组。 - 设备路径错误:不同系统的TTY设备路径不同,比如Linux下常见USB串口为
/dev/ttyUSB0,macOS下可能是/dev/tty.usbserial-xxxx,需根据实际设备调整路径。
此外,原代码还存在其他潜在问题:
- 打开
log.txt仅用O_WRONLY,若文件不存在会直接失败,需添加O_CREAT | O_TRUNC参数创建文件并清空原有内容,同时指定文件权限(如0644)。 - 错误提示仅输出简单文本,无法定位具体问题,建议用
perror()打印系统级错误描述。 - 判断
END的逻辑有缺陷:若read一次读取字节数不足3,或END被拆分到两次读取中,无法触发退出条件。 - 未检查
fd_out的打开结果,也未处理fd_out的关闭错误。
修复后的完整代码
#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main(){ int fd_in = open("/dev/ttys000", O_RDONLY); printf("The file descriptor is: %d\n", fd_in); if(fd_in == -1){ perror("Error in opening device"); return 1; } // 打开/创建log.txt,设置文件权限为0644 int fd_out= open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); if(fd_out == -1){ perror("Error in opening log file"); close(fd_in); return 1; } char buf[20]; ssize_t bytes_read; // 维护3字节缓冲区,用于检测"END"字符串 char end_buf[3] = {0}; while ((bytes_read = read(fd_in, buf, sizeof(buf))) > 0) { write(fd_out, buf, bytes_read); // 逐字节移位检测"END" for(int i=0; i<bytes_read; i++){ end_buf[0] = end_buf[1]; end_buf[1] = end_buf[2]; end_buf[2] = buf[i]; if(strcmp(end_buf, "END") == 0){ goto exit_loop; // 触发退出循环 } } } exit_loop: // 先关闭输出文件,再关闭输入设备 if(close(fd_out) == -1){ perror("Error in closing log file"); } if(close(fd_in) == -1){ perror("Error in closing the device"); } return 0; }
额外说明
- 本地测试时,需确认
/dev/ttys000是真实存在且可访问的串口设备,若使用USB转串口,需替换为对应设备路径。 perror()会输出如"Permission denied"(权限不足)、"No such file or directory"(设备不存在)等具体错误信息,便于快速定位问题。
内容的提问来源于stack exchange,提问作者Ali Ghosn
相关产品推荐
相关产品推荐

