《2022年2022年华工操作系统实验》由会员分享,可在线阅读,更多相关《2022年2022年华工操作系统实验(19页珍藏版)》请在金锄头文库上搜索。
1、一、实验步骤:1. 在 linux 下编写一个应用程序, 命名为 an_ch2_1b 。这个程序不断地输出如下行:Those output come from child,系统时间 另外写一个应用程序, 命名为 an_ch2_1a 。 这个程序创建一个子进程,执行 an_ch2_1b 。这个程序不断地输出如下行:Those output come from child,系统时间 观察程序运行的结果,并对你看到的现象进行解释。2. 在 linux 环境下编写一个控制台应用程序,程序中有一个共享的整型变量 shared_var ,初始值为 0;创建一个线程并使其立即与主线程并发执行。新创建的线程与
2、主线程均不断地循环,并输出shared_var 的值。主线程在循环中不断地对shared_var 进行加 1 操作,即每次循环shared_var 被加 1; 而新创建的线程则不断地对shared_var 进行减 1 操作,即每次循环 shared_var 被减 1。观察程序运行的结果,并对你看到的现象进行解释。二、实验数据:an_ch2_1b.cpp 文件:#include #include #include #include #include usingnamespace std; string getTime() / 获取系统时间 time_t timep; time(&timep);
3、char tmp64; strftime(tmp,sizeof (tmp), %Y-%m-%d%H:%M:%S,localtime(&timep); return tmp; int main() while ( true ) string tmn = getTime(); cout Those output come from child, tmn endl; sleep(1); / 为了便于截屏使用sleep() 函数延迟输出 return 0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - -
4、 - - 第 1 页,共 19 页 - - - - - - - - - an_ch2_1a.cpp 文件:#include #include #include #include #include usingnamespace std; int main() pid_t pid;pid = fork(); if (pid = -1) cout fail to create endl; elseif (pid = 0) system(./an_ch2_1b ); return 0; Consoleapp.c 文件: #include #include #include #include int s
5、hared_var = 0; void * thread(void * arg) while (1) printf(in the thread shared_var:%dn, -shared_var); int main() pthread_t pt; int ret = pthread_create(&pt, NULL , ( void *)thread, NULL ); if (ret != 0) printf(fail to create threadn); while (1) printf(in the main shared_var:%dn, +shared_var); pthrea
6、d_join(pt, NULL ); return 0 ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 19 页 - - - - - - - - - 1.生产者消费者问题(信号量)参考教材中的生产者消费者算法,创建5 个进程,其中两个进程为生产者进程, 3 个进程为消费者进程。一个生产者进程试图不断地在一个缓冲中写入大写字母,另一个生产者进程试图不断地在缓冲中写入小写字母。 3 个消费者不断地从缓冲中读取一个字符并输出。为了使得程序的输出易于看到结果,仿照的实例程序,
7、分别在生产者和消费者进程的合适的位置加入一些随机睡眠时间。可选的实验:在上面实验的基础上实现部分消费者有选择地消费某些产品。例如一个消费者只消费小写字符, 一个消费者只消费大写字母,而另一个消费者则无选择地消费任何产品。消费者要消费的产品没有时,消费者进程被阻塞。注意缓冲的管理。2.用线程实现睡觉的理发师问题,(同步互斥方式采用信号量或mutex方式均可)理发师问题的描述:一个理发店接待室有n 张椅子,工作室有1 张椅子;没有顾客时,理发师睡觉;第一个顾客来到时,必须将理发师唤醒;顾客来时如果还有空座的话,他就坐在一个座位上等待;如果顾客来时没有空座位了,他就离开,不理发了;当理发师处理完所有
8、顾客,而又没有新顾客来时,他又开始睡觉。3.读者写者问题教材中对读者写者问题算法均有描述,但这个算法在不断地有读者流的情况下,写者会被阻塞。 编写一个写者优先解决读者写者问题的程序,其中读者和写者均是多个进程,用信号量作为同步互斥机制。1.生产者消费者问题( pro_con.c )#include#include#include#include#include#include#include#defineN 10 / 缓冲区大小为 100char *buffer; int capacity = N; sem_t mutex, empty, full; void * produce_1() wh
9、ile (1) sem_wait(&empty); sem_wait(&mutex); int r1 = rand() % 26; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 19 页 - - - - - - - - - int ju = 0; for (int i = 0; i N ; i+) if (bufferi = 0 ) bufferi = A + r1; printf(生产者 1号生产一个产品 : %c 剩余容量为: %dn, bufferi, -capa
10、city); ju = 1; break ; if (ju = 0)printf(没有足够容量! n ); sem_post(&mutex); sem_post(&full); usleep(r1 * 100000); void * produce_2() while (1) sem_wait(&empty); sem_wait(&mutex); int r2 = rand() % 26; int ju = 0; for (int i = 0; i N ; i+) if (bufferi = 0 ) bufferi = a + r2; printf(生产者 2号生产一个产品 : %c 剩余容量
11、为: %dn, bufferi, -capacity); ju = 1; break ; if (ju = 0)printf(没有足够容量! n ); sem_post(&mutex); sem_post(&full); usleep(r2 * 100000); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 19 页 - - - - - - - - - void * consume_1() while (1) sem_wait(&full); sem_wait(&mut
12、ex); int ju = 0; for ( int i = 0; i = A &bufferi = Z ) printf(消费者 1号消费一个产品 : %c 剩余容量为: %dn, bufferi, +capacity); bufferi = 0 ; ju = 1; break ; if (ju = 0)printf( 没有消费者 1号所需的产品! n ); sem_post(&mutex); sem_post(&empty); int r3 = rand() % 26; usleep(r3 * 100000); void * consume_2() while (1) sem_wait(&
13、full); sem_wait(&mutex); int ju = 0; for ( int i = 0; i = a &bufferi = z ) printf(消费者 2号消费一个产品 : %c 剩余容量为: %dn, bufferi, +capacity); bufferi = 0 ; ju = 1; break ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 19 页 - - - - - - - - - if (ju = 0)printf( 没有消费者 2号所
14、需的产品! n ); sem_post(&mutex); sem_post(&empty); int r4 = rand() % 26; usleep(r4 * 100000); void * consume_3() int ju = 0; while (1) sem_wait(&full); sem_wait(&mutex); int ju = 0; for ( int i = 0; i = A & bufferi = a & bufferi = z ) printf(消费者 3号消费一个产品 : %c 剩余容量为: %dn, bufferi, +capacity); bufferi = 0
15、 ; ju = 1; break ; if (ju = 0)printf( 没有产品可以消费!n ); sem_post(&mutex); sem_post(&empty); int r5 = rand() % 26; usleep(r5 * 100000); int main() buffer = (char *)malloc(N * sizeof ( char*); for ( int i = 0; i N ; i+) bufferi = 0 ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - -
16、- - - 第 6 页,共 19 页 - - - - - - - - - sem_init(&mutex, 1, 1); sem_init(&empty, 0, N ); sem_init(&full, 0, 0); srand(time(0); pthread_t tid5; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tid0,&attr,produce_1,NULL ); pthread_create(&tid1,&attr,produce_2,NULL ); pthread_create(&tid2,&a
17、ttr,consume_1,NULL ); pthread_create(&tid3,&attr,consume_2,NULL ); pthread_create(&tid4,&attr,consume_3,NULL ); for (int i=0;i5;i+) pthread_join(tidi,NULL ); return 0; 2.用线程实现睡觉的理发师问题(barber.c )#include#include#include#include#include#include#defineN 5 sem_t customer,barber; int chairs,waiting = 0,w
18、ork = 0; pthread_mutex_t mutex; void * Barber ( ) printf(无顾客,理发师睡觉 n ); while (1) sem_wait(&customer); pthread_mutex_lock(&mutex); chairs+; pthread_mutex_unlock(&mutex); work = 1; printf ( 理发师正在给一名顾客理发. %d 个顾客正在接待室等待。n , 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第
19、 7 页,共 19 页 - - - - - - - - - -waiting); sleep(2); printf ( 一名顾客理发完成。n ); work = 0; sem_post(&barber); if (waiting = 0)printf( 无顾客,理发师睡觉 n ); void * Customer ( void * arg ) int *p = (int *) arg ; int x = *p; pthread_mutex_lock(&mutex); if ( chairs 0 ) chairs-; sem_post(&customer); if (waiting = 0 &
20、work = 0) printf( 第 %d 个顾客进来 , 唤醒理发师 .n , +x); waiting+; else printf ( 第 %d 个顾客进来 , %d 个顾客正在接待室等待.n , x+1 , +waiting ); pthread_mutex_unlock(&mutex); sem_wait(&barber); else pthread_mutex_unlock(&mutex); printf ( 第 %d 个顾客进来,没有座位而离开!n , x+1 ); int main ( ) sem_init (&customer , 0 , 0 ); sem_init (&ba
21、rber , 0 , 1 ); chairs = N ; pthread_t bar; pthread_t cusN*100; int cus_idN*100; pthread_create ( &bar , NULL , Barber , NULL ); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 19 页 - - - - - - - - - int i; srand(time(0); for ( i = 0 ; i N*100 ; i + ) usleep(100
22、000*(rand() % 30); cus_idi = i; pthread_create ( &cusi , NULL , Customer , &cus_idi ); pthread_join ( bar , NULL ); for ( i = 0 ; i N*100 ; i+ ) pthread_join ( cus_idi , NULL ); 3.读者写者问题( reader_writer.c)# include# include# include# include# include# include# include# includesem_t RWMutex, mutex1, m
23、utex2, mutex3, wrt; int writeCount, readCount; structdata int id; int lastTime; ; void * Reader( void * param) int id = (structdata *) param)-id; int lastTime = (structdata *) param)-lastTime; printf(读进程 %d 等待读入 n , id); sem_wait(&mutex3); sem_wait(&RWMutex); sem_wait(&mutex2); readCount+; if (readC
24、ount = 1) sem_wait(&wrt); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 19 页 - - - - - - - - - sem_post(&mutex2); sem_post(&RWMutex); sem_post(&mutex3); printf(读进程 %d 开始读入, %d 秒后完成 n , id, lastTime); sleep(lastTime); printf(读进程 %d 完成读入 n , id); sem_wait(&mutex
25、2); readCount-; if (readCount = 0) sem_post(&wrt); sem_post(&mutex2); pthread_exit(0); void * Writer(void * param) int id = (structdata *) param)-id; int lastTime = (structdata *) param)-lastTime; printf(写进程 %d 等待写入 n , id); sem_wait(&mutex1); writeCount+; if (writeCount = 1) sem_wait(&RWMutex); sem
26、_post(&mutex1); sem_wait(&wrt); printf(写进程 %d 开始写入, %d 秒后完成 n , id, lastTime); sleep(lastTime); printf(写进程 %d 完成写入 n , id); sem_post(&wrt); sem_wait(&mutex1); writeCount-; if (writeCount = 0) sem_post(&RWMutex); sem_post(&mutex1); pthread_exit(0); int main() pthread_t tid; pthread_attr_t attr; pthre
27、ad_attr_init(&attr); sem_init(&mutex1, 0, 1); sem_init(&mutex2, 0, 1); sem_init(&mutex3, 0, 1); sem_init(&wrt, 0, 1); sem_init(&RWMutex, 0, 1); readCount = writeCount = 0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 19 页 - - - - - - - - - int id = 0; srand(
28、time(0); while (1) int role = rand() % 100; int lastTime = rand() % 10; id+; structdata* d = (structdata*)malloc(sizeof ( structdata ); d-id = id; d-lastTime = lastTime; if (role = 50) / 写 printf( 创建写进程, PID : %dn , id); pthread_create(&tid, &attr, Writer, d); sleep(rand() % 8); return 0; 名师资料总结 - -
29、 -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 19 页 - - - - - - - - - 1.实现一个“ difftree”命令,其功能是比较两个目录下的文件结构和文件信息。当在命令行方式下执行 “difftree ” 命令时,能够比较目录 dir1 和 目录 dir2 是否具有相同的结构,对相同的部分,进一步比较相同文件名的文件内容。列出比较的文件系统结构图。本实验是对单个文件比较的扩展,设计中需要考虑目录操作。difftree.c #include#include#include#
30、include#include#include#includeint filelevel1 = 0, filelevel2 = 0; char DIRNAME1256, DIRNAME2256; void my_error(constchar * strerr) perror(strerr); exit(1); void findfile(char fileName1 , chardirentName1 , char direntName2 ) char command512 = diff ; DIR *p_dir = NULL ; structdirent *p_dirent = NULL
31、; p_dir = opendir(direntName2 ); if (p_dir = NULL ) my_error(opendir error); while (p_dirent = readdir(p_dir) != NULL ) char *backupDirName = NULL ; if (p_dirent-d_name0 = .)continue ; int i; if (p_dirent-d_type = DT_DIR) int curDirentNameLen = strlen(direntName2 ) + 1; backupDirName = (char *)mallo
32、c(curDirentNameLen); memset(backupDirName, 0, curDirentNameLen); memcpy(backupDirName, direntName2 , curDirentNameLen); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 19 页 - - - - - - - - - strcat(direntName2 , / ); strcat(direntName2 , p_dirent-d_name); findf
33、ile(fileName1 , direntName1 , direntName2 ); memcpy(direntName2 , backupDirName, curDirentNameLen); free(backupDirName); backupDirName = NULL ; elseif (!strcmp(fileName1 , p_dirent-d_name) char FileDirName256; strcpy(FileDirName, direntName2 ); int curDirentNameLen = strlen(direntName2 ) + 1; backup
34、DirName = (char *)malloc(curDirentNameLen); memset(backupDirName, 0, curDirentNameLen); memcpy(backupDirName, FileDirName, curDirentNameLen); strcat(FileDirName, / ); strcat(FileDirName, p_dirent-d_name); strcat(command, direntName1 ); strcat(command, ); strcat(command, FileDirName); printf(%s%sn, p
35、_dirent-d_name, 文件相同,比较: ); system(command); closedir(p_dir); void comparefile(chardirentName1 , char direntName2 ) char command512; DIR *p_dir = NULL ; structdirent *p_dirent = NULL ; p_dir = opendir(direntName1 ); if (p_dir = NULL ) my_error(opendir error); while (p_dirent = readdir(p_dir) != NULL
36、 ) char *backupDirName = NULL ; if (p_dirent-d_name0 = .) continue ; int i; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 19 页 - - - - - - - - - if (p_dirent-d_type = DT_DIR) int curDirentNameLen = strlen(direntName1 ) + 1; backupDirName = (char *)malloc(curD
37、irentNameLen); memset(backupDirName, 0, curDirentNameLen); memcpy(backupDirName, direntName1 , curDirentNameLen); strcat(direntName1 , / ); strcat(direntName1 , p_dirent-d_name); comparefile(direntName1 , direntName2 ); memcpy(direntName1 , backupDirName, curDirentNameLen); free(backupDirName); back
38、upDirName = NULL ; else char FileDirName256; strcpy(FileDirName, direntName1 ); int curDirentNameLen = strlen(direntName1 ) + 1; backupDirName = (char *)malloc(curDirentNameLen); memset(backupDirName, 0, curDirentNameLen); memcpy(backupDirName, FileDirName, curDirentNameLen); strcat(FileDirName, / )
39、; strcat(FileDirName, p_dirent-d_name); findfile(p_dirent-d_name, FileDirName, direntName2 ); closedir(p_dir); void PrintDirentStruct(char direntName , intlevel ) DIR *p_dir = NULL ; structdirent *p_dirent = NULL ; p_dir = opendir(direntName ); if (p_dir = NULL ) my_error(opendir error); while (p_di
40、rent = readdir(p_dir) != NULL ) char *backupDirName = NULL ; if (p_dirent-d_name0 = .) continue ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 19 页 - - - - - - - - - int i; for (i = 0; i d_name); / 如果目录项仍是一个目录的话,进入目录if (p_dirent-d_type = DT_DIR) int curDiren
41、tNameLen = strlen(direntName ) + 1; backupDirName = (char *)malloc(curDirentNameLen); memset(backupDirName, 0, curDirentNameLen); memcpy(backupDirName, direntName , curDirentNameLen); strcat(direntName , / ); strcat(direntName , p_dirent-d_name); level += 1; PrintDirentStruct(direntName , level ); m
42、emcpy(direntName , backupDirName, curDirentNameLen); free(backupDirName); backupDirName = NULL ; closedir(p_dir); int main() memset(DIRNAME1, 0, sizeof (DIRNAME1); memset(DIRNAME2, 0, sizeof (DIRNAME2); scanf(%s%s , DIRNAME1, DIRNAME2); printf(%sn , 第一个目录: ); PrintDirentStruct(DIRNAME1, filelevel1);
43、 printf(n ); printf(%sn , 第二个目录: ); PrintDirentStruct(DIRNAME2, filelevel2); if (filelevel1 = filelevel2)printf(n 两个目录文件结构相同n ); comparefile(DIRNAME1, DIRNAME2); return 0; 1.在 linux中实现一个命令执行程序doit ,它执行命令行参数中的命令之名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 19
44、 页 - - - - - - - - - 后统计1)命令执行占用的 CPU 时间( 包括用户态和系统态时间, 以毫秒为单位 ) ,2)命令执行的时间,3)进程被抢占的次数,4)进程主动放弃 CPU的次数,5)进程执行过程中发生缺页的次数2.在 linux中实现一个简单的命令解释程序,功能要求:1)同时支持内部命令和外部命令,内部命令支持两个(cd、exit )2)支持后台命令提示:实验中可能用到的系统调用如下:? fork() 创建一个新进程? getrusage() 取得进程的资源使用情况? gettimeofday() 取当前的时间? execve() 装入一个程序并执行? wait()
45、等待子进程结束? chdir() 改变进程的工作目录? str tok() 字符串解析1. doit.c #include #include #include #include #include #include #include externinterrno ; int main( intargc , char *argv) char command200; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 19 页 - - - - - - - - - structti
46、meval start, end; strcpy(command, argv 1); for ( int i = 2; i argc; i+) strcat(command, ); strcat(command, argvi); gettimeofday(&start, NULL ); system(command); gettimeofday(&end, NULL ); if ( errno != 0) printf(error:%sn, strerror(errno ); exit(0); else structrusage result; memset(&result, 0, sizeo
47、f ( structrusage ); getrusage(RUSAGE_CHILDREN, &result); double time = (double )end.tv_sec - (double )start.tv_sec) * 1000 + ( double )end.tv_usec - (double )start.tv_usec) / 1000; printf(n 命令执行占用的 CPU 时间 : 用户态 :%f毫秒 t 系统态 :%f毫秒 n , (double )result.ru_utime.tv_usec / 1000 + (double )result.ru_utime.
48、tv_sec * 1000, (double )result.ru_stime.tv_usec / 1000 + (double )result.ru_stime.tv_sec * 1000); printf( 命令执行时间 :%f毫秒n , time); printf( 进程被抢占的次数 :%ldn , result.ru_nivcsw); printf( 进程主动放弃 CPU 的次数 :%ldn , result.ru_nvcsw); printf( 进程执行过程中发生缺页的次数:%ldn , result.ru_majflt); return 0; 2. shell.c #include
49、 #include #include #include #include #include #defineNDEBUG#defineMAX_CMD_LEN 256 #defineMAX_TOKEN_NUM 80 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 19 页 - - - - - - - - - #defineHOME /externinterrno ; void Route() long size; char *buf; char *cwd; size = p
50、athconf(. , _PC_PATH_MAX); if (buf = (char *)malloc(size_t )size) != NULL ) cwd = getcwd(buf, (size_t )size); printf(%s$ , cwd); void getcmd( char * cmd ) while ( cmd0 = getchar() = ); int i = 0; do i+; cmd i = getchar(); while ( cmd i != n&i MAX_CMD_LEN) perror( 命令行的长度超限 ); Route(); cmd i = 0; int
51、main() char cmd MAX_CMD_LEN + 1; printf(enter sehll.n); while (1) Route(); memset(cmd, 0, sizeof (cmd); getcmd(cmd); if (strncmp(cmd, exit, 4) = 0) printf(Successful exit .n); break ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 19 页 - - - - - - - - - if (st
52、rncmp(cmd, cd , 2) = 0) printf( now do cd. n); char *path = (char *)malloc(MAX_CMD_LEN + 1); if (path = NULL ) printf(memery set failn); exit(0); int i = 2; while (cmdi = ) i+; int j = 0; while (cmdi != 0) pathj+ = cmdi+; pathj = 0; chdir(path); if ( errno != 0) printf(error:%sn, strerror(errno ); exit(0); printf(now the path is :%sn, path); free(path); else system(cmd); if ( errno != 0) printf(error:%sn, strerror(errno ); exit(0); return 0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 19 页,共 19 页 - - - - - - - - -