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

作业社区

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

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; }

得分 100
学习任务

浪潮君 的学生作业:

#include #include #include #include #include // ---------------- 全局变量与同步机制 ---------------- // // 共享资源:产品库存数量 static int number = 0; // 所有生产者计划生产的总产品数量 static int total_of_produce = 0; // 当前已消费产品数量 static int total_of_consume = 0; // 互斥锁和条件变量,确保线程安全与同步 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // ---------------- 结构体定义:生产者线程参数 ---------------- // typedef struct { int count; // 当前线程要生产的产品数量 int id; // 当前线程编号 } ProducerArg; // ---------------- 线程函数:生产者 ---------------- // void *producer_thread(void *arg) { ProducerArg *parg = (ProducerArg *)arg; for (int i = 0; i < parg->count; i++) { pthread_mutex_lock(&mutex); // 加锁,进入临界区 number++; // 增加产品库存 printf("生产者[%d] 生产了一个产品,总库存:%d\n", parg->id, number); pthread_cond_signal(&cond); // 通知一个等待中的消费者 pthread_mutex_unlock(&mutex); // 解锁,离开临界区 usleep(rand() % 500000); // 模拟生产耗时(随机延迟) } free(parg); // 释放参数结构体内存 return NULL; } // ---------------- 主函数:创建线程 + 主线程做消费者 ---------------- // int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "用法: %s ...\n", argv[0]); return EXIT_FAILURE; } int num_producers = argc - 1; pthread_t tids[num_producers]; // 存储每个生产者线程的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; if (pthread_create(&tids[i], NULL, producer_thread, parg) != 0) { perror("线程创建失败"); free(parg); return EXIT_FAILURE; } } // ---------------- 主线程作为消费者 ---------------- // while (true) { pthread_mutex_lock(&mutex); // 如果库存为 0,则阻塞等待生产者 signal while (number == 0) { pthread_cond_wait(&cond, &mutex); } // 有产品可消费 number--; total_of_consume++; printf("消费者 消费了一个产品,剩余库存:%d\n", number); bool done = (total_of_consume >= total_of_produce); pthread_mutex_unlock(&mutex); sleep(1); // 模拟消费时间 if (done) { break; // 所有产品已消费完毕,退出循环 } } // 等待所有生产者线程结束 for (int i = 0; i < num_producers; i++) { pthread_join(tids[i], NULL); } // 销毁同步原语 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); printf("所有产品已被消费完毕,共消费:%d 个\n", total_of_consume); return 0; }

得分 100
学习任务

胡汉三66 的学生作业:

#include #include #include #include // bzore() #include // close() #include #include #include #include #include #include #include // pthread_creat() #define BACKLOG 10 // 监听队列最大值 void *do_process_client(void *arg){ // 子线程函数 ssize_t rbytes = 0,sbytes = 0; char buffer[1024] = {0}; int cfd = *(int *)arg; // 获取 客户端套接字 文件描述符 for(;;){ rbytes = recv(cfd,buffer,sizeof(buffer),0); if(rbytes == -1){ perror("[ERROR] Failed to recv."); pthread_exit(NULL); // 退出当前线程 }else if(rbytes > 0){ // 如果收到数据 sbytes = send(cfd,buffer,strlen(buffer),0); if(sbytes == -1){ perror("[ERROR] Failed to socket."); pthread_exit(NULL); // 退出当前线程 } }else if(rbytes == 0){ printf("The client has been shutdown.\n"); break; } } close(cfd); pthread_exit(NULL); // 退出当前线程 } // TCP服务器连接 // ./a.out ip port int main(int argc, const char *argv[]) { int sfd,ret,cfd; struct sockaddr_in svr_addr,cli_addr; pthread_t tid; // 子线程ID int length; socklen_t len = sizeof(struct sockaddr_in); if(argc != 3){ fprintf(stderr,"Usage : %s < ip > < port >.\n",argv[0]); exit(EXIT_FAILURE); } // 1.创建套接字 sfd = socket(AF_INET,SOCK_STREAM,0); if(sfd == -1){ perror("[ERROR] Failed to socket."); exit(EXIT_FAILURE); } printf("sfd = %d\n",sfd); bzero(&svr_addr,sizeof(struct sockaddr_in)); // 指针指向空间初始化(清零) svr_addr.sin_family = AF_INET; // 协议族 svr_addr.sin_port = htons(atoi(argv[2])); // 端口 svr_addr.sin_addr.s_addr = inet_addr(argv[1]); // IP // 2.绑定ip地址与端口号 ret = bind(sfd,(const struct sockaddr *)&svr_addr,sizeof(struct sockaddr_in)); if(ret == -1){ perror("[ERROR] Failed to bind."); exit(EXIT_FAILURE); } // 3.建立监听队列 ret = listen(sfd,BACKLOG); if(ret == -1){ perror("[ERROR] Failed to listen."); exit(EXIT_FAILURE); } for(;;){ // 4.建立连接,并产生新的客户端用于数据收发 cfd = accept(sfd,(struct sockaddr *)&cli_addr,&len); if(cfd == -1){ perror("[ERROR] Failed to accept."); exit(EXIT_FAILURE); } printf("ip : %s port : %d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port)); ret = pthread_create(&tid,NULL,do_process_client,(void *)&cfd); if(ret != 0){ fprintf(stderr,"pthread_create(): %s\n",strerror(ret)); exit(EXIT_FAILURE); } pthread_detach(tid); // 分离子线程 // 程序结束时,系统会释放子线程资源 } close(sfd); // 关闭 文件描述符 return 0; } 【图片】

得分 100
学习任务

浪潮君 的学生作业:

#include #include #include #include // 全局变量,所有线程共享,用于计数 static int global = 0; // 互斥锁,用于保护对 global 的并发访问 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 线程函数:每个线程执行 loops 次 global++ void *do_thread(void *arg) { // 将通用指针 arg 转换为 int*,再解引用取值 int loops = *(int *) arg; // 每次循环加锁、修改 global、解锁 for (int i = 0; i < loops; i++) { pthread_mutex_lock(&mutex); // 加锁,防止其他线程同时访问 global global++; // 累加全局变量 pthread_mutex_unlock(&mutex); // 解锁,允许其他线程进入 } return NULL; // 返回 NULL 表示无返回值 } int main(int argc, char *argv[]) { // ---------------- 参数校验开始 ---------------- // 程序需要一个参数,作为每个线程的循环次数 if (argc != 2) { fprintf(stderr, "参数错误!\n"); fprintf(stderr, "用法:%s \n", argv[0]); fprintf(stderr, "示例:%s 100000\n", argv[0]); fprintf(stderr, "说明:必须传入一个正整数作为参数,表示每个线程执行的加法次数。\n"); exit(EXIT_FAILURE); } // ---------------- 参数解析(strtol 更安全) ---------------- char *endptr = NULL; // 将字符串转换为 long 类型,支持输入较大的数字 long val = strtol(argv[1], &endptr, 10); // base 10 表示十进制 // 检查是否为纯数字,是否为正数 if (*endptr != '\0' || val

微信客服

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

帮助反馈 APP下载

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

公众号

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