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

作业社区

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

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

jelasin 的学生作业:

#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc,char *argv[]) { fd_set read_fds; int pipefd[2]; if(pipe(pipefd) < 0) { perror("pipe"); return 1; } FD_ZERO(&read_fds); FD_SET(pipefd[0], &read_fds); pid_t pid = fork(); if(pid < 0) { perror("fork"); return 1; } else if(pid == 0) { close(pipefd[0]); while (true) { printf("child: waiting for input\n"); char buf[100]; read(0, buf, 100); write(pipefd[1], buf, strlen(buf)); printf("child: wrote %lu bytes: %s\n", strlen(buf), buf); if (strcmp(buf, "exit\n") == 0) { break; } } close(pipefd[1]); exit(0); } else { sleep(1); close(pipefd[1]); char buf[100]; while (true) { int ret = select(pipefd[0] + 1, &read_fds, NULL, NULL, NULL); if(ret < 0) { perror("select"); } else if(ret == 0) { printf("timeout\n"); } else { if(FD_ISSET(pipefd[0], &read_fds)) { printf("pipe is ready to read\n"); read(pipefd[0], buf, 100); printf("read %lu bytes: %s\n", strlen(buf), buf); if (strcmp(buf, "exit\n") == 0) { break; } } } } close(pipefd[0]); waitpid(pid, NULL, 0); } return 0; } ➜ 5 ./main child: waiting for input aaachild: wrote 3 bytes: aaa child: waiting for input pipe is ready to read read 3 bytes: aaa bbbbchild: wrote 4 bytes: bbbb child: waiting for input pipe is ready to read read 4 bytes: bbbb exit child: wrote 5 bytes: exit pipe is ready to read read 5 bytes: exit

得分 100
学习任务

蜡笔小方哎 的学生作业:

创建两个进程,一个进程负责将文件数据写入共享内存,一个进程负责从共享内存读取数据并保存成文件 #include #include #include #include #include #include #include #define SHM_PATH "." #define SHM_PROJ_ID 'X' #define SHM_SZ 100 int main(int argc, char* argv[]) { key_t key; int shmid; void* addr; char buf[SHM_SZ]; FILE* fp; if(argc < 2) { printf("Usage: %s filename\n", argv[0]); return 0; } fp = fopen(argv[1], "r"); if(fp == NULL) { perror("fopen() error!\n"); exit(-1); } key = ftok(SHM_PATH, SHM_PROJ_ID); if(key == -1) { perror("ftok() error!\n"); fclose(fp); exit(-1); } printf("key = %d\n", key); shmid = shmget(key, SHM_SZ, IPC_CREAT | 0644); if(shmid == -1) { perror("shmget() error!\n"); fclose(fp); exit(-1); } printf("shmid = %d\n", shmid); addr = shmat(shmid, NULL, 0); if(addr == (void*)-1) { perror("shmat() error!\n"); fclose(fp); exit(-1); } memset(addr, 0, SHM_SZ); while(1) { if(strcmp(addr, "") != 0) { // 如果读进程没有将共享内存清空,就等待 usleep(20); continue; } memset(buf, 0, SHM_SZ); if(fgets(buf, SHM_SZ, fp) == NULL) { strcpy(addr, "quit"); break; } strcpy(addr, buf); } if(shmdt(addr) == -1) { perror("shmdt() error!\n"); fclose(fp); exit(-1); } sleep(1); // 等待一秒是为了确保在读进程退出之后再删除共享内 if(shmctl(shmid, IPC_RMID, NULL) == -1) { perror("shmctl() error!\n"); fclose(fp); exit(-1); } fclose(fp); return 0; } #include #include #include #include #include #include #include #define SHM_PATH "." #define SHM_PROJ_ID 'X' #define SHM_SZ 100 int main() { key_t key; int shmid; void* addr; char buf[SHM_SZ]; FILE* fp; fp = fopen("copy.txt", "w"); if(fp == NULL) { perror("fopen() error!\n"); exit(-1); } key = ftok(SHM_PATH, SHM_PROJ_ID); if(key == -1) { perror("ftok() error!\n"); fclose(fp); exit(-1); } printf("key = %d\n", key); shmid = shmget(key, SHM_SZ, IPC_CREAT | 0644); if(shmid == -1) { perror("shmget() error!\n"); fclose(fp); exit(-1); } printf("shmid = %d\n", shmid); addr = shmat(shmid, NULL, 0); if(addr == (void*)-1) { perror("shmat() error!\n"); fclose(fp); exit(-1); } while(1) { memset(buf, 0, SHM_SZ); strcpy(buf, addr); if(strcmp(buf, "") == 0) { // 从共享内存拿到空数据,表示写进程还没有输入 usleep(20); continue; } // 拿到数据后清空共享内存 memset(addr, 0, SHM_SZ); if(strcmp(buf, "quit") == 0) break; fputs(buf, fp); } if(shmdt(addr) == -1) { perror("shmdt() error!\n"); fclose(fp); exit(-1); } fclose(fp); return 0; }

得分 100
学习任务

jelasin 的学生作业:

#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int number = 0;//共享变量 int total_of_produce = 0; // 总的生产产品的数量 int total_of_consume = 0; // 总的消费产品的数量 bool done = false; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; void *product_handler(void *arg) { int cnt = atoi((char *)arg); int i,tmp; for(i = 0;i < cnt;i++) { pthread_mutex_lock(&mtx); printf("线程 [%ld] 生产一个产品,产品数量为:%d\n",pthread_self(),++number); pthread_cond_broadcast(&cond); // 唤醒消费者线程 pthread_mutex_unlock(&mtx); } pthread_exit((void *)0); } void* consumer_handler(void *arg) { pthread_mutex_lock(&mtx); while(number == 0) // 当产品数量为 0时,让线程阻塞,并释放锁,这里一般设置循环,防止没有重新获取到锁 pthread_cond_wait(&cond,&mtx); while(number > 0) { total_of_consume++; // 消费产品总数 printf("消费一个产品,产品数量为:%d\n",--number); done = total_of_consume >= total_of_produce; // 判断消费者数量与产品数量 } pthread_mutex_unlock(&mtx); // 消费者消费完成之后,释放锁 pthread_exit((void *)0); } int main(int argc,char *argv[]) { pthread_t tid; int i; int err; for (i = 1;i < argc;i++) { total_of_produce += atoi(argv[i]); // 生产数量的总和 err = pthread_create(&tid,NULL,product_handler,(void *)argv[i]); if (err != 0) { perror("[ERROR] pthread_create(): "); exit(EXIT_FAILURE); } pthread_detach(tid); // 线程分离,不等待线程结束 } while (done == false) { err = pthread_create(&tid,NULL,consumer_handler,NULL); if (err != 0) { perror("[ERROR] pthread_create(): "); exit(EXIT_FAILURE); } pthread_detach(tid); // 线程分离,不等待线程结束 sleep(1); // 等待1秒钟,防止消费者线程阻塞 } return 0; } ➜ 5 ./main 10 10 10 线程 [138990789330496] 生产一个产品,产品数量为:1 线程 [138990789330496] 生产一个产品,产品数量为:2 线程 [138990789330496] 生产一个产品,产品数量为:3 线程 [138990789330496] 生产一个产品,产品数量为:4 线程 [138990789330496] 生产一个产品,产品数量为:5 线程 [138990642529856] 生产一个产品,产品数量为:6 线程 [138990642529856] 生产一个产品,产品数量为:7 线程 [138990757873216] 生产一个产品,产品数量为:8 线程 [138990757873216] 生产一个产品,产品数量为:9 线程 [138990757873216] 生产一个产品,产品数量为:10 线程 [138990757873216] 生产一个产品,产品数量为:11 线程 [138990757873216] 生产一个产品,产品数量为:12 线程 [138990757873216] 生产一个产品,产品数量为:13 线程 [138990757873216] 生产一个产品,产品数量为:14 线程 [138990757873216] 生产一个产品,产品数量为:15 线程 [138990757873216] 生产一个产品,产品数量为:16 线程 [138990757873216] 生产一个产品,产品数量为:17 消费一个产品,产品数量为:16 消费一个产品,产品数量为:15 消费一个产品,产品数量为:14 消费一个产品,产品数量为:13 消费一个产品,产品数量为:12 消费一个产品,产品数量为:11 消费一个产品,产品数量为:10 消费一个产品,产品数量为:9 消费一个产品,产品数量为:8 消费一个产品,产品数量为:7 消费一个产品,产品数量为:6 消费一个产品,产品数量为:5 消费一个产品,产品数量为:4 消费一个产品,产品数量为:3 消费一个产品,产品数量为:2 消费一个产品,产品数量为:1 消费一个产品,产品数量为:0 线程 [138990789330496] 生产一个产品,产品数量为:1 线程 [138990789330496] 生产一个产品,产品数量为:2 线程 [138990642529856] 生产一个产品,产品数量为:3 线程 [138990789330496] 生产一个产品,产品数量为:4 线程 [138990789330496] 生产一个产品,产品数量为:5 线程 [138990789330496] 生产一个产品,产品数量为:6 线程 [138990642529856] 生产一个产品,产品数量为:7 线程 [138990642529856] 生产一个产品,产品数量为:8 线程 [138990642529856] 生产一个产品,产品数量为:9 线程 [138990642529856] 生产一个产品,产品数量为:10 线程 [138990642529856] 生产一个产品,产品数量为:11 线程 [138990642529856] 生产一个产品,产品数量为:12 线程 [138990642529856] 生产一个产品,产品数量为:13 消费一个产品,产品数量为:12 消费一个产品,产品数量为:11 消费一个产品,产品数量为:10 消费一个产品,产品数量为:9 消费一个产品,产品数量为:8 消费一个产品,产品数量为:7 消费一个产品,产品数量为:6 消费一个产品,产品数量为:5 消费一个产品,产品数量为:4 消费一个产品,产品数量为:3 消费一个产品,产品数量为:2 消费一个产品,产品数量为:1 消费一个产品,产品数量为:0 发送信号,通知等待在条件上的线程,然后解锁互斥量。注意范例代码中先发送信号,然后解锁互斥量,这个顺序不是必须的,也可以颠倒。标准允许任意顺序执行这两个调用。先通知条件变量、后解锁互斥量,效率会比先解锁、后通知条件变量低。因为先通知后解锁,执行pthread_cond_wait的线程可能在互斥量已然处于加锁状态的时候醒来,发现互斥量仍然没有解锁,就会再次休眠,从而导致了多余的上下文切换。某些实现使用等待变形(wait morphing)来优化这个问题:并不真正地唤醒执行pthread_cond_wait的线程,而是将线程从条件变量的等待队列转移到互斥量的等待队列上,从而消除无谓的上下文切换。 glibc对pthread_cond_broadcast做了类似的优化,即只唤醒一个线程,将其他线程从条件变量的等待队列搬移到了互斥量的等待队列中。 先解锁、后通知条件变量虽然可能会有性能上的优势,但是也会带来其他的问题。如果存在一个高优先级的线程,既等待在互斥量上,也等待在条件变量上;同时还存在一个低优先级的线程,只等待在互斥量上。一旦先解锁互斥量,低优先级的进程就可能会抢先获得互斥量,待调用pthread_cond_signal之后,高优先级的进程会发现互斥量已经被低优先级的进程抢走了。

得分 100
学习任务

jelasin 的学生作业:

#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include void *thread1_func(void *arg) { char *stack = NULL; printf("stack address: %p\n", &stack); printf("#1: KThread id: %d\n", gettid()); printf("#1: PThread id: %lu\n", pthread_self()); return NULL; } void *thread2_func(void *arg) { char *stack = NULL; printf("stack address: %p\n", &stack); printf("#2: KThread id: %d\n", gettid()); printf("#2: PThread id: %lu\n", pthread_self()); return NULL; } int main() { pthread_t thread1, thread2; if (pthread_create(&thread1, NULL, thread1_func, NULL)!= 0) { perror("pthread_create #1"); return 1; } if (pthread_create(&thread2, NULL, thread2_func, NULL)!= 0) { perror("pthread_create #2"); return 1; } pthread_detach(thread1); pthread_detach(thread2); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&thread1, &attr, thread1_func, NULL)!= 0) { perror("pthread_create #3"); return 1; } if (pthread_create(&thread2, &attr, thread2_func, NULL)!= 0) { perror("pthread_create #4"); return 1; } pthread_exit(NULL); return 0; } ➜ 5 ./main stack address: 0x7783c3dffe40 #1: KThread id: 15176 #1: PThread id: 131407810659904 stack address: 0x7783c33ffe40 #2: KThread id: 15177 #2: PThread id: 131407800174144 stack address: 0x7783bbdffe40 #1: KThread id: 15178 #1: PThread id: 131407676442176 stack address: 0x7783c29ffe40 #2: KThread id: 15179 #2: PThread id: 131407789688384

微信客服

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

帮助反馈 APP下载

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

公众号

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