为了账号安全,请及时绑定邮箱和手机立即绑定

作业社区

探索学习新天地,共享知识资源!

0 提交作业
0 布置作业
0 满分作业
得分 100
学习任务

浪潮君 的学生作业:

#include // 标准输入输出 #include // 提供 exit() 等函数 #include // 提供 memset() #include // 提供 open() 和 O_NONBLOCK #include // epoll 相关函数和结构体 #include // mkfifo() 创建 FIFO #include // read()、close() 等 #define MAXEVENTS 10 // epoll_wait 返回事件的最大数量 #define FIFO_PATH "/tmp/myfifo"// 有名管道路径 int main(void) { int epfd, ret, fifo_fd; // epoll 实例、返回值、FIFO 文件描述符 struct epoll_event ev; // 注册到 epoll 的事件 struct epoll_event ret_ev[MAXEVENTS]; // epoll_wait 返回的事件数组 char buffer[256] = {0}; // 读缓冲区 // 创建有名管道(如果已经存在会报错,可忽略) if (mkfifo(FIFO_PATH, 0666) == -1) { perror("[INFO] mkfifo (可忽略 if already exists)"); } // 打开 FIFO 文件为非阻塞读模式(注意:没有写端时 read 会返回 0) fifo_fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK); if (fifo_fd == -1) { perror("[ERROR] 打开 FIFO 失败"); exit(EXIT_FAILURE); } // 创建 epoll 实例,返回 epoll 文件描述符 epfd = epoll_create(1); if (epfd == -1) { perror("[ERROR] 创建 epoll 实例失败"); exit(EXIT_FAILURE); } // 配置监听事件:监听 FIFO 的“可读”事件 ev.data.fd = fifo_fd; // 要监听的文件描述符 ev.events = EPOLLIN; // 表示监听“可读事件” ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fifo_fd, &ev); // 注册到 epoll if (ret == -1) { perror("[ERROR] 注册 epoll 事件失败"); exit(EXIT_FAILURE); } printf("开始监听 FIFO:%s\n", FIFO_PATH); // 主事件循环(永久监听) while (1) { // 阻塞等待事件发生,超时时间为 1000 毫秒 ret = epoll_wait(epfd, ret_ev, MAXEVENTS, 1000); if (ret == -1) { perror("[ERROR] 等待事件失败"); exit(EXIT_FAILURE); } else if (ret == 0) { // 超时无事件发生 printf("无数据,等待中...\n"); } else { // 有一个或多个事件发生 for (int i = 0; i < ret; ++i) { if (ret_ev[i].events & EPOLLIN) { // FIFO 可读,尝试读取数据 memset(buffer, 0, sizeof(buffer)); ssize_t n = read(fifo_fd, buffer, sizeof(buffer) - 1); if (n > 0) { // 正常读取数据 printf("收到数据:%s\n", buffer); } else if (n == 0) { // 写端关闭,FIFO 被“挂断”,需要重新打开 printf("[INFO] FIFO 写端关闭,尝试重新打开...\n"); close(fifo_fd); // 重新以只读非阻塞方式打开 FIFO fifo_fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK); if (fifo_fd == -1) { perror("[ERROR] 重新打开 FIFO 失败"); exit(EXIT_FAILURE); } // 重新注册到 epoll(旧 fd 已关闭) ev.data.fd = fifo_fd; epoll_ctl(epfd, EPOLL_CTL_ADD, fifo_fd, &ev); } } } } } // 程序退出前清理资源(理论上此处不会到达) close(epfd); close(fifo_fd); return 0; }

得分 100
学习任务

浪潮君 的学生作业:

#include #include #include #include #include #include #include #define FIFO_PATH "/tmp/myfifo" // 有名管道路径 #define BUFFER_SIZE 1024 int main(void) { int fd, ret; struct pollfd pfds; char buffer[BUFFER_SIZE] = {0}; // 创建有名管道(FIFO) // 0666 表示所有用户都有读写权限 if (mkfifo(FIFO_PATH, 0666) == -1) { // 忽略管道已存在的错误,否则退出 if (errno != EEXIST) { perror("[ERROR] mkfifo()"); exit(EXIT_FAILURE); } } // 以非阻塞只读模式打开管道 // O_NONBLOCK 确保 open() 和 read() 不会阻塞 fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("[ERROR] open()"); exit(EXIT_FAILURE); } // 设置 poll 监听结构 pfds.fd = fd; // 监听管道文件描述符 pfds.events = POLLIN; // 监听可读事件 printf("监听管道 %s ...\n", FIFO_PATH); printf("可在另一个终端执行 'echo \"test\" > %s' 发送数据\n", FIFO_PATH); // 主循环:持续监听管道事件 for (;;) { // 调用 poll 监听事件,-1 表示无限等待 ret = poll(&pfds, 1, -1); if (ret == -1) { // poll 调用失败 perror("[ERROR] poll()"); exit(EXIT_FAILURE); } else if (ret > 0) { // 有事件发生,检查是否为可读事件 if (pfds.revents & POLLIN) { // 清空缓冲区 memset(buffer, 0, BUFFER_SIZE); // 从管道读取数据 ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE - 1); if (bytes_read == -1) { // 读取失败 perror("[ERROR] read()"); exit(EXIT_FAILURE); } else if (bytes_read == 0) { // 读取到 0 字节,表示所有写端已关闭 printf("管道已关闭,等待新连接...\n"); // 关闭并重新打开管道,以等待新的写端连接 close(fd); fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("[ERROR] reopen()"); exit(EXIT_FAILURE); } pfds.fd = fd; // 更新 pollfd 中的文件描述符 } else { // 成功读取数据,打印内容 printf("读取到数据: %s", buffer); } } } // ret == 0 表示超时,这里不会触发(timeout=-1) } // 程序正常不会执行到这里,可添加清理代码 close(fd); // 关闭管道 unlink(FIFO_PATH); // 删除管道文件(可选) return 0; }

微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号