
作業(yè)社區(qū)
探索學(xué)習(xí)新天地,共享知識(shí)資源!
浪潮君 的學(xué)生作業(yè):
#include #include #include #include // 定義一個(gè)結(jié)構(gòu)體 Person,包含名字和年齡 typedef struct { char name[20]; int age; } Person; // 子線程的函數(shù),用于創(chuàng)建并返回一個(gè)結(jié)構(gòu)體指針 void *thread_func(void *) { // 動(dòng)態(tài)分配結(jié)構(gòu)體內(nèi)存(分配到堆上,避免線程棧退出后失效) Person *p = malloc(sizeof(*p)); if (NULL == p) { perror("malloc failed"); pthread_exit(NULL); // 分配失敗時(shí),線程安全退出 } // 初始化結(jié)構(gòu)體數(shù)據(jù) strcpy(p->name, "Tom"); p->age = 28; // 將結(jié)構(gòu)體指針作為線程返回值傳遞回主線程 return p; } int main(int argc, char *argv[]) { pthread_t tid; // 線程 ID Person *result = NULL; // 用于接收子線程返回的結(jié)構(gòu)體指針 // 創(chuàng)建子線程,執(zhí)行 thread_func 函數(shù) if (pthread_create(&tid, NULL, thread_func, NULL) != 0) { perror("線程創(chuàng)建失敗"); exit(EXIT_FAILURE); } // 等待子線程結(jié)束,并獲取返回值(結(jié)構(gòu)體指針) if (pthread_join(tid, (void **)&result) != 0) { perror("pthread_join"); exit(EXIT_FAILURE); } // 打印結(jié)構(gòu)體內(nèi)容(驗(yàn)證子線程傳遞的數(shù)據(jù)) if (result != NULL) { printf("姓名:%s\n", result->name); printf("年齡:%d\n", result->age); } // 釋放堆內(nèi)存,防止內(nèi)存泄漏 free(result); return 0; }





浪潮君 的學(xué)生作業(yè):
#include #include #include #include // 線程A的函數(shù) void *thread_A(void *arg) { for (int i = 0; i < 3; i++) { printf("線程A:第 %d 次執(zhí)行\(zhòng)n", i + 1); sleep(1); // 模擬耗時(shí)操作 } pthread_exit(NULL); // 顯式退出線程(可省略) } // 線程B的函數(shù) void *thread_B(void *arg) { for (int i = 0; i < 3; i++) { printf("線程B:第 %d 次執(zhí)行\(zhòng)n", i + 1); sleep(1); // 模擬耗時(shí)操作 } pthread_exit(NULL); } int main() { pthread_t tid_A, tid_B; // 聲明兩個(gè)線程ID // 創(chuàng)建線程A if (pthread_create(&tid_A, NULL, thread_A, NULL) != 0) { perror("創(chuàng)建線程A失敗"); exit(EXIT_FAILURE); } // 創(chuàng)建線程B if (pthread_create(&tid_B, NULL, thread_B, NULL) != 0) { perror("創(chuàng)建線程B失敗"); exit(EXIT_FAILURE); } // 設(shè)置線程A、B為分離狀態(tài): // 一旦線程執(zhí)行完,系統(tǒng)自動(dòng)釋放資源,不需要主線程回收 pthread_detach(tid_A); pthread_detach(tid_B); // 因?yàn)榫€程是分離狀態(tài),主線程不能使用 join 來(lái)等待它們 // 為防止主線程提前退出,我們 sleep 一段時(shí)間,確保子線程有時(shí)間完成 sleep(5); // 等待足夠的時(shí)間(3次sleep(1) ≈ 3秒,預(yù)留2秒緩沖) printf("主線程結(jié)束(不等待子線程)\n"); return 0; }





浪潮君 的學(xué)生作業(yè):
#include #include #include #include // 線程A的任務(wù)函數(shù) void *thread_A(void *arg) { for (int i = 0; i < 5; i++) { printf("線程A正在運(yùn)行,第 %d 次\n", i + 1); sleep(1); } return NULL; } // 線程B的任務(wù)函數(shù) void *thread_B(void *arg) { for (int i = 0; i < 5; i++) { printf("線程B正在運(yùn)行,第 %d 次\n", i + 1); sleep(1); } return NULL; } int main() { pthread_t tid_A, tid_B; // 創(chuàng)建線程A if (pthread_create(&tid_A, NULL, thread_A, NULL) != 0) { perror("創(chuàng)建線程A失敗"); exit(EXIT_FAILURE); } // 創(chuàng)建線程B if (pthread_create(&tid_B, NULL, thread_B, NULL) != 0) { perror("創(chuàng)建線程B失敗"); exit(EXIT_FAILURE); } // 等待兩個(gè)線程執(zhí)行結(jié)束 pthread_join(tid_A, NULL); pthread_join(tid_B, NULL); printf("主線程結(jié)束。\n"); return 0; }





浪潮君 的學(xué)生作業(yè):
#include #include #include #include #include #include #include #define LOOP_COUNT 10 // 定義循環(huán)次數(shù)(輸出多少行) #define OUTPUT_FILE "output.txt" // 輸出文件名 int main() { int pipefd[2]; // pipefd[0] 是讀端,pipefd[1] 是寫(xiě)端。用于父子進(jìn)程間同步通信 // 創(chuàng)建管道,pipefd[0] 為讀端,pipefd[1] 為寫(xiě)端 if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } // 創(chuàng)建子進(jìn)程 pid_t pid = fork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } if (pid == 0) { // ---------------------- 子進(jìn)程邏輯 ---------------------- close(pipefd[1]); // 子進(jìn)程不寫(xiě)管道,只用讀管道,所以關(guān)閉寫(xiě)端 // 子進(jìn)程單獨(dú)打開(kāi)輸出文件(使用追加模式),防止和父進(jìn)程共享文件描述符沖突 int fd = open(OUTPUT_FILE, O_WRONLY | O_APPEND); if (fd == -1) { perror("child open"); exit(EXIT_FAILURE); } for (int i = 1; i





Linkus 的學(xué)生作業(yè):
// 請(qǐng)創(chuàng)建一個(gè)信號(hào)量集合,里面包含兩個(gè)信號(hào)量,分別初始化為 0 和 1 #include #include #include #include #include #include #define PATHNAME "./" #define PROJ_ID 100 union semun{ int val; }; int main() { int semid,ret; union semun s; key_t key = ftok(PATHNAME,PROJ_ID); if(key == -1) { perror("[ERR] ftok() : "); return -1; } semid = semget(key,2,IPC_CREAT | 0644); if(semid == -1) { perror("[ERR] semget() : "); return -1; } s.val = 0; ret = semctl(semid, 0, SETVAL, s); if(ret == -1) { perror("[ERR] semctl() : "); return -1; } s.val = 1; ret = semctl(semid, 1, SETVAL, s); if(ret == -1) { perror("[ERR] semctl() : "); return -1; } return 0; }





胡漢三66 的學(xué)生作業(yè):
client.c #include #include #include #include // bzore() #include // close() #include #include #include #include // TCP客戶端連接 // ./a.out ip port int main(int argc, const char *argv[]) { int sfd,ret; ssize_t sbytes = 0; char buffer[1024] = "Hello,server"; char *pbuffer = NULL; int length = 0; struct sockaddr_in svr_addr; if(argc != 3){ fprintf(stderr,"Usage : %s < ip > < port >.\n",argv[0]); exit(EXIT_FAILURE); } // 1.創(chuàng)建套接字 sfd = socket(AF_INET,SOCK_STREAM,0); if(sfd == -1){ perror("[ERROR] Failed to socket."); exit(EXIT_FAILURE); } // 2.建立連接 bzero(&svr_addr,sizeof(struct sockaddr_in)); // 指針指向空間初始化(清零) svr_addr.sin_family = AF_INET; // 協(xié)議族 svr_addr.sin_port = htons(atoi(argv[2])); // 端口 svr_addr.sin_addr.s_addr = inet_addr(argv[1]); // IP ret = connect(sfd,(const struct sockaddr *)&svr_addr,sizeof(struct sockaddr_in)); // 客戶端 連接 服務(wù)器 if(ret == -1){ perror("[ERROR] Failed to connect."); exit(EXIT_FAILURE); } for(;;){ // 循環(huán)輸入發(fā)送 length = strlen(buffer); pbuffer = (char *)malloc(length + 4); memcpy(pbuffer,&length,4); // 存儲(chǔ)字節(jié)數(shù) memcpy(pbuffer + 4,buffer,length); // 存儲(chǔ)數(shù)據(jù)內(nèi)容 sbytes = send(sfd,pbuffer,length + 4,0); if(sbytes == -1){ perror("[ERROR] Failed to send."); exit(EXIT_FAILURE); } usleep(100); // 休息100微妙 // 100微妙 = 0.0001秒 } close(sfd); // 關(guān)閉 文件描述符 return 0; } server.c #include #include #include #include // bzore() #include // close() #include #include #include #include #define BACKLOG 10 // 監(jiān)聽(tīng)隊(duì)列最大值 // TCP服務(wù)器連接 // ./a.out ip port int main(int argc, const char *argv[]) { int sfd,ret,cfd; struct sockaddr_in svr_addr,cli_addr; ssize_t rbytes = 0,sbytes = 0; char buffer[1024] = {0}; int length; int total_received; // 統(tǒng)計(jì)當(dāng)前接收的總字節(jié)數(shù) socklen_t len = sizeof(struct sockaddr_in); if(argc != 3){ fprintf(stderr,"Usage : %s < ip > < port >.\n",argv[0]); exit(EXIT_FAILURE); } // 1.創(chuàng)建套接字 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; // 協(xié)議族 svr_addr.sin_port = htons(atoi(argv[2])); // 端口 svr_addr.sin_addr.s_addr = inet_addr(argv[1]); // IP // 2.綁定ip地址與端口號(hào) ret = bind(sfd,(const struct sockaddr *)&svr_addr,sizeof(struct sockaddr_in)); if(ret == -1){ perror("[ERROR] Failed to bind."); exit(EXIT_FAILURE); } // 3.建立監(jiān)聽(tīng)隊(duì)列 ret = listen(sfd,BACKLOG); if(ret == -1){ perror("[ERROR] Failed to listen."); exit(EXIT_FAILURE); } // 4.建立連接,并產(chǎn)生新的客戶端用于數(shù)據(jù)收發(fā) 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)); for(;;){ length = 0; int total_received = 0; // 統(tǒng)計(jì)當(dāng)前接收的總字節(jié)數(shù) rbytes = recv(cfd,&length,4,0); if(rbytes == -1){ perror("[ERROR] Failed to recv."); exit(EXIT_FAILURE); } for(;;){ rbytes = recv(cfd,buffer + total_received,length - total_received,0); if(rbytes == -1){ perror("[ERROR] Failed to recv."); exit(EXIT_FAILURE); }else if(rbytes > 0){ // 如果收到數(shù)據(jù) total_received += rbytes; if(total_received == length) break; }else if(rbytes == 0){ printf("The client has been shutdown.\n"); break; } } printf("buffer : %s\n",buffer); sleep(1); // 休息1秒 } close(sfd); // 關(guān)閉 文件描述符 close(cfd); return 0; } 【圖片】





浪潮君 的學(xué)生作業(yè):
#include #include #include #include #include // 定義一個(gè)結(jié)構(gòu)體,封裝兩個(gè)命名信號(hào)量的指針,便于統(tǒng)一管理和傳遞 typedef struct { sem_t *sem_zero; // 信號(hào)量1,初始值為 0,常用于“等待條件滿足” sem_t *sem_one; // 信號(hào)量2,初始值為 1,常用于“互斥訪問(wèn)”或資源令牌 } SemaphoreSet; int main() { SemaphoreSet semaphores; // 聲明信號(hào)量集合結(jié)構(gòu)體變量 // 使用 sem_open 創(chuàng)建命名信號(hào)量: // 參數(shù)含義: // - 名字以 / 開(kāi)頭(是 POSIX 命名要求) // - O_CREAT | O_EXCL 表示“如果已存在則報(bào)錯(cuò)” // - 0644 是文件權(quán)限 // - 最后一個(gè)參數(shù)是初始值 semaphores.sem_zero = sem_open("/sem_zero", O_CREAT | O_EXCL, 0644, 0); // 初始為 0 semaphores.sem_one = sem_open("/sem_one", O_CREAT | O_EXCL, 0644, 1); // 初始為 1 // 錯(cuò)誤檢查:如果 sem_zero 創(chuàng)建失敗,立即退出 if (semaphores.sem_zero == SEM_FAILED) { perror("sem_open sem_zero failed"); exit(EXIT_FAILURE); } // 錯(cuò)誤檢查:如果 sem_one 創(chuàng)建失敗,釋放 sem_zero 并退出(回滾清理) if (semaphores.sem_one == SEM_FAILED) { perror("sem_open sem_one failed"); sem_close(semaphores.sem_zero); // 關(guān)閉 sem_zero 引用 sem_unlink("/sem_zero"); // 刪除系統(tǒng)中的 sem_zero 信號(hào)量 exit(EXIT_FAILURE); } // 如果兩個(gè)信號(hào)量都成功創(chuàng)建,打印提示信息 printf("命名信號(hào)量集合已初始化:/sem_zero = 0, /sem_one = 1\n"); // 關(guān)閉兩個(gè)信號(hào)量的引用(釋放當(dāng)前進(jìn)程持有的句柄) sem_close(semaphores.sem_zero); sem_close(semaphores.sem_one); // 刪除命名信號(hào)量,釋放系統(tǒng)內(nèi)核資源 sem_unlink("/sem_zero"); sem_unlink("/sem_one"); return 0; }





胡漢三66 的學(xué)生作業(yè):
1.粘包原因:底層邏輯:TCP協(xié)議子啊底層是字節(jié)流,并不關(guān)注應(yīng)用層的消息邊界。具體分兩類發(fā)送方和接收方. 1-1. 發(fā)送方一: 發(fā)送多個(gè)較小數(shù)據(jù)包,一般是小于內(nèi)核緩沖區(qū)大小。默認(rèn)情況下,tcp采用Nagle算法,會(huì)合并連續(xù)的小數(shù)據(jù)包一次性發(fā)送,形成粘包。 1-2. 發(fā)送方二: 發(fā)送一個(gè)大數(shù)據(jù)包,大數(shù)據(jù)包大于MTU(最大輸出單元),會(huì)發(fā)生拆包,將字節(jié)流進(jìn)行切片分成多個(gè)包進(jìn)行發(fā)送,拆分后的大數(shù)據(jù)包形成粘包。 2. 接收方: 客戶端發(fā)送的速度大于服務(wù)器接收的速度,在緩沖區(qū)緩存了多個(gè)數(shù)據(jù)包,服務(wù)器一次性讀取,則會(huì)讀取多個(gè)數(shù)據(jù)包,也就是粘包。 client.c #include #include #include #include // bzore() #include // close() #include #include #include #include // TCP客戶端連接 // ./a.out ip port int main(int argc, const char *argv[]) { int sfd,ret; ssize_t sbytes = 0, rbytes = 0; char buffer[1024] = {0}; struct sockaddr_in svr_addr; if(argc != 3){ fprintf(stderr,"Usage : %s < ip > < port >.\n",argv[0]); exit(EXIT_FAILURE); } // 1.創(chuàng)建套接字 sfd = socket(AF_INET,SOCK_STREAM,0); if(sfd == -1){ perror("[ERROR] Failed to socket."); exit(EXIT_FAILURE); } // 2.建立連接 bzero(&svr_addr,sizeof(struct sockaddr_in)); // 指針指向空間初始化(清零) svr_addr.sin_family = AF_INET; // 協(xié)議族 svr_addr.sin_port = htons(atoi(argv[2])); // 端口 svr_addr.sin_addr.s_addr = inet_addr(argv[1]); // IP ret = connect(sfd,(const struct sockaddr *)&svr_addr,sizeof(struct sockaddr_in)); // 客戶端 連接 服務(wù)器 if(ret == -1){ perror("[ERROR] Failed to connect."); exit(EXIT_FAILURE); } for(;;){ // 循環(huán)輸入發(fā)送 // 獲取數(shù)據(jù) strcpy(buffer,"Hello,server"); // 3.發(fā)送數(shù)據(jù) (客戶端-->服務(wù)器) sbytes = send(sfd,buffer,strlen(buffer),0); // "+1" ---> "\0" if(sbytes == -1){ perror("[ERROR] Failed to send."); exit(EXIT_FAILURE); } usleep(100); // 休息100微妙 // 100微妙 = 0.0001秒 } close(sfd); // 關(guān)閉 文件描述符 return 0; } server.c #include #include #include #include // bzore() #include // close() #include #include #include #include #define BACKLOG 10 // 監(jiān)聽(tīng)隊(duì)列最大值 // TCP服務(wù)器連接 // ./a.out ip port int main(int argc, const char *argv[]) { int sfd,ret,cfd; struct sockaddr_in svr_addr,cli_addr; ssize_t rbytes = 0,sbytes = 0; char buffer[1024] = {0}; socklen_t len = sizeof(struct sockaddr_in); if(argc != 3){ fprintf(stderr,"Usage : %s < ip > < port >.\n",argv[0]); exit(EXIT_FAILURE); } // 1.創(chuàng)建套接字 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; // 協(xié)議族 svr_addr.sin_port = htons(atoi(argv[2])); // 端口 svr_addr.sin_addr.s_addr = inet_addr(argv[1]); // IP // 2.綁定ip地址與端口號(hào) ret = bind(sfd,(const struct sockaddr *)&svr_addr,sizeof(struct sockaddr_in)); if(ret == -1){ perror("[ERROR] Failed to bind."); exit(EXIT_FAILURE); } // 3.建立監(jiān)聽(tīng)隊(duì)列 ret = listen(sfd,BACKLOG); if(ret == -1){ perror("[ERROR] Failed to listen."); exit(EXIT_FAILURE); } // 4.建立連接,并產(chǎn)生新的客戶端用于數(shù)據(jù)收發(fā) 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)); for(;;){ memset(buffer,0,sizeof(buffer)); // 清空 rbytes = recv(cfd,buffer,sizeof(buffer),0); if(rbytes == -1){ perror("[ERROR] Failed to recv."); exit(EXIT_FAILURE); }else if(rbytes > 0){ // 如果收到數(shù)據(jù) printf("buffer : %s\n",buffer); }else if(rbytes == 0){ printf("The client has been shutdown.\n"); break; } sleep(1); // 休息1秒 } close(sfd); // 關(guān)閉 文件描述符 close(cfd); return 0; } 【圖片】





浪潮君 的學(xué)生作業(yè):
int main(int argc, char *argv[]) { // 參數(shù)檢查:至少需要輸入生產(chǎn)者數(shù)量、消費(fèi)者數(shù)量,以及每個(gè)生產(chǎn)者的產(chǎn)品數(shù)量 if (argc < 3) { fprintf(stderr, "用法: %s ... \n", argv[0]); exit(EXIT_FAILURE); } // 解析命令行參數(shù)中的生產(chǎn)者數(shù)量和消費(fèi)者數(shù)量 int producer_num = atoi(argv[1]); int consumer_num = atoi(argv[2]); // 邊界檢查,防止生產(chǎn)者或消費(fèi)者數(shù)量超出預(yù)設(shè)最大值范圍 if (producer_num MAX_PRODUCERS || consumer_num MAX_CONSUMERS) { fprintf(stderr, "生產(chǎn)者或消費(fèi)者數(shù)量超出范圍(最大%d/%d)\n", MAX_PRODUCERS, MAX_CONSUMERS); exit(EXIT_FAILURE); } // 檢查參數(shù)數(shù)量是否正確,為每個(gè)生產(chǎn)者都指定了生產(chǎn)數(shù)量 if (argc != 3 + producer_num) { fprintf(stderr, "請(qǐng)為每個(gè)生產(chǎn)者指定生產(chǎn)數(shù)量\n"); exit(EXIT_FAILURE); } // 定義數(shù)組,用于保存生產(chǎn)者和消費(fèi)者線程ID pthread_t producer_tids[producer_num]; pthread_t consumer_tids[consumer_num]; int total_produce = 0; // 統(tǒng)計(jì)所有生產(chǎn)者生產(chǎn)的產(chǎn)品總數(shù) // 創(chuàng)建生產(chǎn)者線程 for (int i = 0; i < producer_num; i++) { // 為當(dāng)前生產(chǎn)者分配參數(shù)結(jié)構(gòu)體內(nèi)存 ProducerArg *parg = malloc(sizeof(ProducerArg)); parg->produce_count = atoi(argv[3 + i]); // 解析生產(chǎn)數(shù)量 parg->id = i + 1; // 生產(chǎn)者編號(hào)從1開(kāi)始 total_produce += parg->produce_count; // 累加總生產(chǎn)數(shù)量 // 創(chuàng)建生產(chǎn)者線程,傳入?yún)?shù)結(jié)構(gòu)體 if (pthread_create(&producer_tids[i], NULL, producer_thread, parg) != 0) { perror("pthread_create producer"); exit(EXIT_FAILURE); } } // 創(chuàng)建消費(fèi)者線程 for (int i = 0; i < consumer_num; i++) { // 為當(dāng)前消費(fèi)者分配參數(shù)結(jié)構(gòu)體內(nèi)存 ConsumerArg *carg = malloc(sizeof(ConsumerArg)); carg->id = i + 1; // 消費(fèi)者編號(hào)從1開(kāi)始 // 創(chuàng)建消費(fèi)者線程,傳入?yún)?shù)結(jié)構(gòu)體 if (pthread_create(&consumer_tids[i], NULL, consumer_thread, carg) != 0) { perror("pthread_create consumer"); exit(EXIT_FAILURE); } } // 等待所有生產(chǎn)者線程結(jié)束,確保所有產(chǎn)品已生產(chǎn)完畢 for (int i = 0; i < producer_num; i++) { pthread_join(producer_tids[i], NULL); } // 通知消費(fèi)者所有生產(chǎn)者已完成生產(chǎn) pthread_mutex_lock(&mtx); all_producers_done = true; pthread_cond_broadcast(&cond); // 喚醒所有可能正在等待的消費(fèi)者線程 pthread_mutex_unlock(&mtx); // 等待所有消費(fèi)者線程結(jié)束,確保所有產(chǎn)品已被消費(fèi) for (int i = 0; i < consumer_num; i++) { pthread_join(consumer_tids[i], NULL); } // 銷(xiāo)毀互斥鎖和條件變量,釋放系統(tǒng)資源 pthread_mutex_destroy(&mtx); pthread_cond_destroy(&cond); // 程序結(jié)束提示 printf("所有產(chǎn)品已生產(chǎn)和消費(fèi)完畢。\n"); return 0; }
浪潮君 的學(xué)生作業(yè):
#include #include #include #include #include // 共享資源:產(chǎn)品數(shù)量 static int number = 0; // 互斥鎖,用于保護(hù)臨界區(qū) pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // 條件變量,用于線程間的同步(通知消費(fèi)者有產(chǎn)品了) pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 生產(chǎn)者線程參數(shù)結(jié)構(gòu)體 typedef struct { int cnt; // 當(dāng)前線程需要生產(chǎn)的產(chǎn)品數(shù)量 int producer_id; // 生產(chǎn)者編號(hào),用于打印 } ProducerArg; // 生產(chǎn)者線程執(zhí)行函數(shù) void *thread_handler(void *arg) { ProducerArg *parg = (ProducerArg *) arg; int cnt = parg->cnt; int id = parg->producer_id; for (int i = 0; i < cnt; i++) { pthread_mutex_lock(&mtx); // 進(jìn)入臨界區(qū) ++number; // 模擬生產(chǎn)一個(gè)產(chǎn)品 printf("線程 [%d] 生產(chǎn)一個(gè)產(chǎn)品,當(dāng)前產(chǎn)品總數(shù): %d\n", id, number); pthread_cond_signal(&cond); // 通知消費(fèi)者線程有新產(chǎn)品 pthread_mutex_unlock(&mtx); // 退出臨界區(qū) usleep(rand() % 500000); // 模擬生產(chǎn)所需的耗時(shí) } free(parg); // 釋放參數(shù)結(jié)構(gòu)體,防止內(nèi)存泄漏 pthread_exit(NULL); // 正常退出線程 } int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "用法: %s ...\n", argv[0]); exit(EXIT_FAILURE); } int num_producers = argc - 1; // 生產(chǎn)者線程數(shù)量 pthread_t tids[num_producers]; // 保存所有線程的 ID int total_of_produce = 0; // 記錄總共需要生產(chǎn)的產(chǎn)品數(shù)量 int total_of_consume = 0; // 記錄已消費(fèi)的產(chǎn)品數(shù)量 // 創(chuàng)建所有生產(chǎn)者線程 for (int i = 0; i < num_producers; i++) { int count = atoi(argv[i + 1]); // 當(dāng)前生產(chǎn)者要生產(chǎn)的產(chǎn)品數(shù)量 total_of_produce += count; // 累加到總生產(chǎn)數(shù)量 // 為每個(gè)線程分配參數(shù)結(jié)構(gòu)體 ProducerArg *parg = malloc(sizeof(ProducerArg)); if (!parg) { perror("malloc"); exit(EXIT_FAILURE); } parg->cnt = count; parg->producer_id = i + 1; // 創(chuàng)建線程 if (pthread_create(&tids[i], NULL, thread_handler, parg) != 0) { perror("pthread_create"); free(parg); exit(EXIT_FAILURE); } } // 主線程作為消費(fèi)者 while (total_of_consume < total_of_produce) { pthread_mutex_lock(&mtx); // 加鎖進(jìn)入臨界區(qū) // 如果當(dāng)前沒(méi)有產(chǎn)品,則等待條件變量 while (number == 0) { pthread_cond_wait(&cond, &mtx); // 自動(dòng)釋放鎖并掛起,收到 signal 后會(huì)自動(dòng)加鎖恢復(fù) } // 有產(chǎn)品可消費(fèi) --number; ++total_of_consume; printf("主線程消費(fèi)一個(gè)產(chǎn)品,剩余產(chǎn)品數(shù): %d\n", number); pthread_mutex_unlock(&mtx); // 解鎖退出臨界區(qū) sleep(1); // 模擬消費(fèi)耗時(shí) } // 等待所有生產(chǎn)者線程退出 for (int i = 0; i < num_producers; i++) { pthread_join(tids[i], NULL); } // 清理資源 pthread_mutex_destroy(&mtx); pthread_cond_destroy(&cond); printf("所有產(chǎn)品已被消費(fèi)完畢,總共消費(fèi) %d 個(gè)產(chǎn)品。\n", total_of_consume); return 0; }
浪潮君 的學(xué)生作業(yè):
#include #include #include #include // 定義一個(gè)全局變量,兩個(gè)線程都會(huì)對(duì)它執(zhí)行加一操作 static int global = 0; // 聲明并初始化互斥鎖 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 子線程函數(shù):對(duì) global 執(zhí)行 loops 次加一操作 void *do_thread(void *arg) { int loops = *(int *)arg; // 從參數(shù)中取出循環(huán)次數(shù) for (int i = 0; i < loops; i++) { pthread_mutex_lock(&mutex); // 加鎖:進(jìn)入臨界區(qū) global++; // 修改共享變量 pthread_mutex_unlock(&mutex); // 解鎖:退出臨界區(qū) } return NULL; // 線程無(wú)返回值 } int main() { pthread_t tid[2]; // 定義兩個(gè)線程 ID int loops = 1000000; // 每個(gè)線程加一百萬(wàn)次,共兩百萬(wàn)次 // 創(chuàng)建兩個(gè)線程,執(zhí)行 do_thread 函數(shù),傳入同一個(gè) loops 參數(shù)地址 for (int i = 0; i < 2; i++) { if (pthread_create(&tid[i], NULL, do_thread, &loops) != 0) { perror("pthread_create failed"); // 創(chuàng)建失敗則報(bào)錯(cuò)并退出 exit(EXIT_FAILURE); } } // 等待兩個(gè)線程執(zhí)行完畢(阻塞主線程) pthread_join(tid[0], NULL); pthread_join(tid[1], NULL); // 輸出最終的 global 值,應(yīng)為 2 × 1000000 = 2000000 printf("global = %d\n", global); return 0; }
浪潮君 的學(xué)生作業(yè):
#include // 提供 printf、perror 等標(biāo)準(zhǔn)輸出函數(shù) #include // 提供 malloc、free、exit 等動(dòng)態(tài)內(nèi)存和退出控制 #include // 提供 pthread 線程函數(shù) #include // 提供字符串處理函數(shù),如 strcpy // 使用匿名結(jié)構(gòu)體定義類型 person typedef struct { char name[20]; // 名字字段,最多 19 個(gè)字符 + '\0' int age; // 年齡字段 } person; // 子線程函數(shù):創(chuàng)建并返回一個(gè) person 結(jié)構(gòu)體指針 void *thread_func(void *) { // 動(dòng)態(tài)分配內(nèi)存,確保線程退出后數(shù)據(jù)依然有效 person *p = malloc(sizeof(person)); if (p == NULL) { perror("malloc failed"); // 分配失敗,打印錯(cuò)誤信息 pthread_exit(NULL); // 線程安全地退出 } // 填寫(xiě)結(jié)構(gòu)體字段 strcpy(p->name, "Tom"); // 設(shè)置名字 p->age = 30; // 設(shè)置年齡 return (void *) p; // 返回結(jié)構(gòu)體指針(會(huì)被 pthread_join 接收) } int main() { pthread_t tid; // 線程 ID person *result = NULL; // 用于接收線程返回的結(jié)構(gòu)體指針 // 創(chuàng)建子線程,執(zhí)行 thread_func 函數(shù) if (pthread_create(&tid, NULL, thread_func, NULL) != 0) { perror("線程創(chuàng)建失敗"); exit(EXIT_FAILURE); // 創(chuàng)建失敗,程序退出 } // 主線程等待子線程結(jié)束,并接收其返回的結(jié)構(gòu)體地址 if (pthread_join(tid, (void **) &result) != 0) { perror("線程等待失敗"); exit(EXIT_FAILURE); } // 如果接收成功,打印結(jié)構(gòu)體中的數(shù)據(jù) if (result != NULL) { printf("姓名:%s\n", result->name); printf("年齡:%d\n", result->age); free(result); // 使用完后釋放動(dòng)態(tài)內(nèi)存,防止內(nèi)存泄漏 } return 0; }
浪潮君 的學(xué)生作業(yè):
#include // 標(biāo)準(zhǔn)輸入輸出函數(shù),如 printf、fprintf #include // 提供 exit() 和 EXIT_FAILURE 宏 #include // 提供 fork()、sleep() 等系統(tǒng)調(diào)用 #include // 提供 wait() 函數(shù),等待子進(jìn)程 #include // 提供時(shí)間函數(shù),如 time()、strftime() #include // 提供文件控制宏(本程序中未使用,可刪除) int main() { // 打開(kāi)日志文件,寫(xiě)入模式,如果文件存在則清空,不存在則創(chuàng)建 FILE *fp = fopen("time_log.txt", "w"); if (fp == NULL) { perror("無(wú)法打開(kāi)文件"); exit(EXIT_FAILURE); // 打開(kāi)失敗則退出程序 } // 循環(huán) 10 次,每次創(chuàng)建一個(gè)子進(jìn)程,完成一次完整的時(shí)間日志寫(xiě)入 for (int i = 1; i
浪潮君 的學(xué)生作業(yè):
#include // 提供 printf() #include // 提供 exit() #include // 提供 POSIX 線程函數(shù) #include // 提供 sleep() // 子線程執(zhí)行函數(shù) void* thread_func(void *) { // 獲取當(dāng)前線程的 ID pthread_t tid = pthread_self(); // 打印線程 ID(轉(zhuǎn)換為無(wú)符號(hào)長(zhǎng)整型便于輸出) printf("子線程(分離)ID: %lu\n", (unsigned long) tid); // 線程結(jié)束(返回 NULL) return NULL; } int main() { pthread_t tid1, tid2; // 定義兩個(gè)線程變量,用于保存線程 ID // 創(chuàng)建第一個(gè)線程 if (pthread_create(&tid1, NULL, thread_func, NULL) != 0) { perror("創(chuàng)建線程 1 失敗"); exit(EXIT_FAILURE); } // 設(shè)置第一個(gè)線程為分離狀態(tài)(不再使用 pthread_join 等待它) pthread_detach(tid1); // 創(chuàng)建第二個(gè)線程 if (pthread_create(&tid2, NULL, thread_func, NULL) != 0) { perror("創(chuàng)建線程 2 失敗"); exit(EXIT_FAILURE); } // 設(shè)置第二個(gè)線程為分離狀態(tài) pthread_detach(tid2); // 主線程暫停 1 秒,等待子線程運(yùn)行完畢 sleep(1); // 否則主線程太早結(jié)束,子線程可能還沒(méi)執(zhí)行就被強(qiáng)制終止 // 主線程結(jié)束 printf("主線程結(jié)束(不等待子線程)\n"); return 0; }