
在嵌入式Linux应用开发中,read和write函数是文件I/O操作中最基础、最常用的两个系统调用。它们用于从文件描述符(file descriptor)指向的文件或设备中读取数据和向其中写入数据。
一、read 函数#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);fd:文件描述符,由 open 函数返回的一个非负整数,用于标识要读取数据的文件、设备等。buf:指向用于存储读取数据的缓冲区的指针,数据将被读取到这个缓冲区中。count:期望读取的字节数,即希望从文件描述符对应的文件或设备中读取的最大字节数。errno 会被设置为相应的错误码,用于指示具体的错误原因。#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[100];
ssize_t bytesRead = read(fd, buffer, sizeof(buffer) - 1);
if (bytesRead == -1) {
perror("read");
close(fd);
return 1;
}
buffer[bytesRead] = '\0'; // 确保字符串以NULL结尾
printf("Read %zd bytes: %s\n", bytesRead, buffer);
close(fd);
return 0;
}
二、write 函数#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);fd:文件描述符,标识要写入数据的文件、设备等。buf:指向包含要写入数据的缓冲区的指针。count:要写入的字节数,即希望将缓冲区中多少字节的数据写入到文件描述符对应的文件或设备中。errno 会被设置为相应的错误码,用于指示具体的错误原因。#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main() {
int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("open");
return 1;
}
const char *message = "Hello, World!\n";
ssize_t bytesWritten = write(fd, message, strlen(message));
if (bytesWritten == -1) {
perror("write");
close(fd);
return 1;
}
printf("Written %zd bytes\n", bytesWritten);
close(fd);
return 0;
}
ssize_t total_read = 0;
while (total_read < count) {
ssize_t n = read(fd, buf + total_read, count - total_read);
if (n == 0) break; // EOF
if (n < 0 && errno != EINTR) break; // 非中断错误
if (n > 0) total_read += n;
}errno值:
EAGAIN/EWOULDBLOCK:非阻塞模式下无数据可读或写缓冲区满。
EINTR:操作被信号中断。
EBADF:无效文件描述符。
EINTR需重试操作。
EAGAIN需结合select/poll等待就绪。
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);fsync(fd)强制将内核缓冲区数据写入存储设备。
pthread_mutex)。
①配置文件读取
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main() {
int fd = open("config.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[BUFFER_SIZE];
ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE);
if (bytes_read == -1) {
perror("read");
} else if (bytes_read > 0) {
buffer[bytes_read] = '\0';
// 处理读取到的配置信息
}
close(fd);
return 0;
}②数据文件写入
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define DATA "25.5"
int main() {
int fd = open("data.txt", O_WRONLY | O_CREAT | O_APPEND, 0644);
if (fd == -1) {
perror("open");
return 1;
}
ssize_t bytes_written = write(fd, DATA, strlen(DATA));
if (bytes_written == -1) {
perror("write");
}
close(fd);
return 0;
}①传感器数据读取
read 函数从相应的设备文件中读取传感器数据。#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define SENSOR_DEVICE "/dev/sensor"
#define BUFFER_SIZE 32
int main() {
int fd = open(SENSOR_DEVICE, O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[BUFFER_SIZE];
ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE);
if (bytes_read == -1) {
perror("read");
} else if (bytes_read > 0) {
buffer[bytes_read] = '\0';
// 处理传感器数据
}
close(fd);
return 0;
}②设备控制命令写入
write 函数向设备文件写入控制命令,从而实现对设备的控制。#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define LED_DEVICE "/dev/led"
#define COMMAND "ON"
int main() {
int fd = open(LED_DEVICE, O_WRONLY);
if (fd == -1) {
perror("open");
return 1;
}
ssize_t bytes_written = write(fd, COMMAND, strlen(COMMAND));
if (bytes_written == -1) {
perror("write");
}
close(fd);
return 0;
}③串口/UART通信
串口设备(如/dev/ttyS0)是嵌入式系统中常见的通信接口,read和write用于收发数据:
// 配置串口后...
char tx_data[] = "Hello UART!";
write(uart_fd, tx_data, strlen(tx_data)); // 发送数据
char rx_data[32];
ssize_t len = read(uart_fd, rx_data, sizeof(rx_data)); // 接收数据①管道通信
write 函数向管道写入数据,另一个进程通过 read 函数从管道读取数据。#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 1024
int main() {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return 1;
}
if (pid == 0) {
// 子进程:读取数据
close(pipefd[1]);
char buffer[BUFFER_SIZE];
ssize_t bytes_read = read(pipefd[0], buffer, BUFFER_SIZE);
if (bytes_read == -1) {
perror("read");
} else if (bytes_read > 0) {
buffer[bytes_read] = '\0';
printf("Child process read: %s\n", buffer);
}
close(pipefd[0]);
} else {
// 父进程:写入数据
close(pipefd[0]);
const char *message = "Hello from parent!";
ssize_t bytes_written = write(pipefd[1], message, strlen(message));
if (bytes_written == -1) {
perror("write");
}
close(pipefd[1]);
}
return 0;
}套接字数据读写
read 函数接收网络数据,使用 write 函数发送网络数据。#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
return 1;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr);
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
close(sockfd);
return 1;
}
const char *message = "Hello, server!";
ssize_t bytes_written = write(sockfd, message, strlen(message));
if (bytes_written == -1) {
perror("write");
}
char buffer[BUFFER_SIZE];
ssize_t bytes_read = read(sockfd, buffer, BUFFER_SIZE);
if (bytes_read == -1) {
perror("read");
} else if (bytes_read > 0) {
buffer[bytes_read] = '\0';
printf("Received from server: %s\n", buffer);
}
close(sockfd);
return 0;
}5.1. read函数常见问题①读取到的字节数少于请求数:
②读取操作失败:
③读取的数据不准确:
5.2. write函数常见问题①写入操作失败:
②写入的字节数少于请求数:
③写入的数据未立即生效:
fsync或fdatasync函数来强制将缓冲区中的数据同步到磁盘。read和write函数时,务必检查返回值,并根据返回值进行相应的错误处理。errno变量来获取更详细的错误信息。read和write函数是嵌入式Linux应用开发中用于文件I/O操作的基础工具。通过这两个函数,可以实现从文件或设备读取数据和向文件或设备写入数据。了解并正确使用这些函数,对于开发稳定、高效的嵌入式应用程序至关重要。