31. IO操作
发布人:shili8
发布时间:2025-01-13 14:49
阅读次数:0
**IO操作**
IO(Input/Output)操作是计算机程序中非常重要的一部分,它负责处理数据的输入和输出。IO操作可以分为两大类:同步IO和异步IO。
###1. 同步IO同步IO是最常见的IO类型,程序在进行IO操作时会阻塞等待IO完成,这意味着如果IO操作需要花费很长时间,整个程序都会被挂起。同步IO通常使用以下函数:
* `read()`:从文件或网络中读取数据* `write()`:向文件或网络中写入数据**示例代码**
c#include <stdio.h>
#include <stdlib.h>
int main() {
// 打开一个文件 FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
printf("无法打开文件
");
return1;
}
char buffer[1024];
// 从文件中读取数据 while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
fclose(fp);
return0;
}
###2. 异步IO异步IO是指程序在进行IO操作时不会阻塞等待IO完成,而是继续执行其他任务。当IO完成后,程序会被通知来处理结果。异步IO通常使用以下函数:
* `aio_read()`:从文件或网络中读取数据* `aio_write()`:向文件或网络中写入数据**示例代码**
c#include <stdio.h>
#include <stdlib.h>
#include <aio.h>
int main() {
// 打开一个文件 int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
printf("无法打开文件
");
return1;
}
struct aiocb *iocb = malloc(sizeof(struct aiocb));
iocb->aio_fildes = fd;
iocb->aio_offset =0;
iocb->aio_buf = malloc(1024);
iocb->aio_nbytes =1024;
iocb->aio_reqprio =0;
// 开始异步读取 if (aio_read(iocb) == -1) {
printf("无法开始读取
");
free(iocb->aio_buf);
close(fd);
return1;
}
// 等待IO完成 aio_wait(NULL, iocb, NULL);
char *data = iocb->aio_buf;
// 处理读取的数据 printf("%s", data);
free(iocb->aio_buf);
close(fd);
return0;
}
###3. IO多路复用IO多路复用是指在一个线程中同时处理多个IO操作,提高了程序的并发性和效率。常用的IO多路复用函数有:
* `select()`:等待一组文件描述符中的任何一个就绪* `poll()`:等待一组文件描述符中的任何一个就绪* `epoll_create()`:创建一个 epoll 对象**示例代码**
c#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int main() {
// 打开两个文件 int fd1 = open("example1.txt", O_RDONLY);
int fd2 = open("example2.txt", O_RDONLY);
if (fd1 == -1 || fd2 == -1) {
printf("无法打开文件
");
return1;
}
// 等待一组文件描述符中的任何一个就绪 fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(fd1, &read_fds);
FD_SET(fd2, &read_fds);
struct timeval timeout;
timeout.tv_sec =5;
timeout.tv_usec =0;
if (select(fd2 +1, &read_fds, NULL, NULL, &timeout) == -1) {
printf("无法等待文件描述符就绪
");
close(fd1);
close(fd2);
return1;
}
// 处理读取的数据 if (FD_ISSET(fd1, &read_fds)) {
char buffer[1024];
read(fd1, buffer, sizeof(buffer));
printf("%s", buffer);
}
if (FD_ISSET(fd2, &read_fds)) {
char buffer[1024];
read(fd2, buffer, sizeof(buffer));
printf("%s", buffer);
}
close(fd1);
close(fd2);
return0;
}
###4. IO复用IO复用是指在一个线程中同时处理多个IO操作,提高了程序的并发性和效率。常用的IO复用函数有:
* `epoll_create()`:创建一个 epoll 对象* `epoll_ctl()`:添加或删除一个文件描述符到 epoll 中**示例代码**
c#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
int main() {
// 打开两个文件 int fd1 = open("example1.txt", O_RDONLY);
int fd2 = open("example2.txt", O_RDONLY);
if (fd1 == -1 || fd2 == -1) {
printf("无法打开文件
");
return1;
}
// 创建一个 epoll 对象 int epfd = epoll_create(10);
if (epfd == -1) {
printf("无法创建 epoll 对象
");
close(fd1);
close(fd2);
return1;
}
struct epoll_event event;
// 添加文件描述符到 epoll 中 event.events = EPOLLIN;
event.data.fd = fd1;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd1, &event) == -1) {
printf("无法添加文件描述符到 epoll 中
");
close(fd1);
close(fd2);
return1;
}
event.events = EPOLLIN;
event.data.fd = fd2;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd2, &event) == -1) {
printf("无法添加文件描述符到 epoll 中
");
close(fd1);
close(fd2);
return1;
}
// 等待一组文件描述符中的任何一个就绪 struct epoll_event events[10];
int num = epoll_wait(epfd, events,10, -1);
if (num == -1) {
printf("无法等待文件描述符就绪
");
close(fd1);
close(fd2);
return1;
}
// 处理读取的数据 for (int i =0; i < num; i++) {
if (events[i].events & EPOLLIN) {
char buffer[1024];
read(events[i].data.fd, buffer, sizeof(buffer));
printf("%s", buffer);
}
}
close(fd1);
close(fd2);
return0;
}
### 总结本文介绍了IO操作的基本概念和常用函数,包括同步IO、异步IO、IO多路复用和IO复用。通过示例代码,可以看到这些函数如何在实际应用中使用。

