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复用。通过示例代码,可以看到这些函数如何在实际应用中使用。