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

作业社区

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

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

浪潮君 的学生作业:

#include // 标准输入输出函数,如 printf #include // 提供 exit、malloc、perror 等函数 #include // 提供 access、read、close 等系统调用 #include // 提供 open、O_RDONLY 等常量 #include // 提供 select() 函数 #include // 提供 mkfifo() 等定义 #include // 提供 memset() 字符处理函数 #define FIFO_PATH "myfifo" // 定义有名管道文件名(路径) int main(void) { int fifo_fd, ret; // 管道文件描述符,select() 的返回值 fd_set readfds, tmpfds; // select() 使用的读文件描述符集合 struct timeval tv = {3, 0}; // 超时时间,3 秒 0 微秒 struct timeval tmp_tv; // 每次循环前要复制 timeval,因为 select 会修改它 char buffer[128] = {0}; // 用于读取数据的缓冲区 // ---------- 步骤1:检查管道是否存在,不存在就创建 ---------- if (access(FIFO_PATH, F_OK) == -1) { // 如果文件不存在 if (mkfifo(FIFO_PATH, 0666) == -1) { // 创建有名管道,权限为 0666 perror("mkfifo"); // 创建失败则输出错误信息 exit(EXIT_FAILURE); // 退出程序 } } // ---------- 步骤2:以只读 + 非阻塞方式打开有名管道 ---------- fifo_fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK); // 非阻塞打开,避免无人写入时卡住 if (fifo_fd == -1) { perror("open fifo"); // 打开失败 exit(EXIT_FAILURE); } // ---------- 步骤3:设置 select 的监听目标 ---------- FD_ZERO(&readfds); // 清空描述符集合 FD_SET(fifo_fd, &readfds); // 把管道文件描述符加入集合 int maxfd = fifo_fd; // 计算最大文件描述符,用于 select 第一个参数 printf("监听管道 %s 中...\n", FIFO_PATH); // 提示监听开始 // ---------- 步骤4:进入循环,不断监听管道是否有数据 ---------- for (;;) { tmp_tv = tv; // select 会修改 timeout,每次循环前重置它 tmpfds = readfds; // 同样复制 fd_set,select 会修改 // ---------- 调用 select 监听 ---------- ret = select(maxfd + 1, &tmpfds, NULL, NULL, &tmp_tv); if (ret == -1) { perror("[ERROR] select(): "); // select 出错 close(fifo_fd); exit(EXIT_FAILURE); } else if (ret == 0) { printf("[INFO] 等待超时,没有数据。\n"); // 超时无数据 } else { // ---------- 如果文件描述符可读 ---------- if (FD_ISSET(fifo_fd, &tmpfds)) { memset(buffer, 0, sizeof(buffer)); // 清空缓冲区 int n = read(fifo_fd, buffer, sizeof(buffer) - 1); // 尝试读取数据 if (n > 0) { printf("[RECV] %s", buffer); // 打印收到的数据 } else if (n == 0) { // 写端关闭,此时读端 read 会返回 0 printf("[INFO] 写端关闭,重新打开 FIFO...\n"); close(fifo_fd); // 关闭旧 fd fifo_fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK); // 重新打开 if (fifo_fd == -1) { perror("reopen fifo"); exit(EXIT_FAILURE); } FD_ZERO(&readfds); // 清空集合重新设置 FD_SET(fifo_fd, &readfds); maxfd = fifo_fd; } } } } close(fifo_fd); return 0; }

得分 100
学习任务

浪潮君 的学生作业:

#include #include #include #include #include // ------------------- 宏定义 ------------------- #define MAX_CONSUMERS 3 // 消费者线程的最大数量 // ------------------- 全局共享资源 ------------------- static int number = 0; // 当前库存产品数量(共享变量) static int total_of_produce = 0; // 所有生产者线程总共要生产的产品数量 static int total_of_consume = 0; // 所有消费者线程总共已消费的产品数量 // ------------------- 线程同步工具 ------------------- static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // 互斥锁,保护临界区(库存、总量等) static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 条件变量,用于线程等待/唤醒 // ------------------- 结构体:线程参数 ------------------- typedef struct { int count; // 当前生产者线程要生产的产品数量 int id; // 当前线程编号(从 1 开始) } ProducersArg; // ------------------- 生产者线程函数 ------------------- void *producer_thread(void *arg) { ProducersArg *parg = (ProducersArg *) arg; for (int i = 0; i < parg->count; i++) { pthread_mutex_lock(&mtx); // 进入临界区,锁定资源 number++; // 库存 +1 printf("生产者[%d] 生产了一个产品,总库存:%d\n", parg->id, number); pthread_cond_broadcast(&cond); // 唤醒所有消费者线程(库存可能可消费了) pthread_mutex_unlock(&mtx); // 解锁,退出临界区 usleep(random() % 500000); // 模拟生产耗时(0~0.5 秒) } free(parg); // 释放传入的参数结构体(堆内存) return NULL; } // ------------------- 消费者线程函数 ------------------- void *consumer_thread(void *arg) { int id = *(int *) arg; // 取出线程编号 free(arg); // 释放编号内存(主线程 malloc 的) while (true) { pthread_mutex_lock(&mtx); // 锁住临界区 // 如果已经消费完所有产品,就退出等待 while (total_of_consume >= total_of_produce) pthread_cond_wait(&cond, &mtx); // 等待生产者唤醒 // 二次判断:是否所有产品都消费完 if (total_of_consume >= total_of_produce) { pthread_mutex_unlock(&mtx); // 解锁后退出 break; } number--; // 消费一个产品 total_of_consume++; // 消费计数器 +1 printf("消费者[%d] 消费了一个产品,剩余库存:%d\n", id, number); pthread_mutex_unlock(&mtx); // 解锁临界区 usleep(random() % 500000); // 模拟消费耗时 } return NULL; } // ------------------- 主线程函数 ------------------- int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "用法: %s ...\n", argv[0]); exit(EXIT_FAILURE); } int num_producers = argc - 1; // 生产者线程数 = 参数数量 - 程序名 pthread_t producers[num_producers]; // 生产者线程 ID 数组 pthread_t consumers[MAX_CONSUMERS]; // 消费者线程 ID 数组 // 创建生产者线程 for (int i = 0; i < num_producers; i++) { char *endptr = NULL; long val = strtol(argv[i + 1], &endptr, 10); // 解析参数 // 参数非法判断:必须是正整数 if (*endptr != '\0' || val count = count; parg->id = i + 1; // 线程编号从 1 开始 // 创建线程 if (pthread_create(&producers[i], NULL, producer_thread, parg) != 0) { perror("pthread_create(生产者)"); free(parg); exit(EXIT_FAILURE); } } // 创建消费者线程 for (int i = 0; i < MAX_CONSUMERS; i++) { int *cid = malloc(sizeof(int)); if (!cid) { perror("malloc"); exit(EXIT_FAILURE); } *cid = i + 1; // 编号从 1 开始 if (pthread_create(&consumers[i], NULL, consumer_thread, cid) != 0) { perror("pthread_create(消费者)"); free(cid); exit(EXIT_FAILURE); } } // 等待所有生产者线程结束 for (int i = 0; i < num_producers; i++) { pthread_join(producers[i], NULL); } // 等待所有消费者线程结束 for (int i = 0; i < MAX_CONSUMERS; i++) { pthread_join(consumers[i], NULL); } // 销毁同步资源 pthread_mutex_destroy(&mtx); pthread_cond_destroy(&cond); printf("所有产品已被消费完毕,总共消费 %d 个\n", total_of_consume); return 0; }

微信客服

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

帮助反馈 APP下载

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

公众号

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