0


NUAA操作系统OS实验及上机考试记录

记录nuaa操作系统实验题目

将代码分享出来是为了学弟学妹更好的学习复习,并不是为copy提供便利。里边包含了平时的job及近几年的考试题,我已将代码上传至github:
https://github.com/changyan-maker/NUAA_OS

最后参加机考我拿了90+,来源于平时认真完成job以及考前认真刷题准备,所以平时不要copy代码投机取巧哦,要理解其中的思路,在机考的过程中才能游刃有余!

文章目录


exam

往年考试题的题目和代码已上传至github,建议考前多刷两遍,
https://github.com/changyan-maker/NUAA_OS
毕竟考试相对综合,个人觉得考前时间充裕的话,先刷一遍作业的job,最后再刷往年考试题会很有感觉。我们19级也就是2022年考的特别难,基本没有几个同学完全运行出正确结果,老师最后都是按照过程给分,这里将题目分享出来只是为了长长见识,毕竟在考试前我也没太见过这种题,考试过程中基本全靠临场发挥。不过前几年的题目还是很简单的,听说拿满分的人也有,所以对于2018、2019、2021年的题目,学弟学妹一定要自己写出来,拿下那些题型!

job3

1. myecho.c

myecho.c的功能与系统echo程序相同
接受命令行参数,并将参数打印出来,例子如下:
$ ./myecho x
x
$ ./myecho a b c
a b c

#include<stdio.h>intmain(int argc,char*argv[]){int i;printf("argc=%d\n",argc);for(i=1;i<argc;i++)printf("%s ",argv[i]);printf("\n");return0;}

2. mycat.c

mycat.c的功能与系统cat程序相同
mycat将指定的文件内容输出到屏幕,例子如下:
要求使用系统调用open/read/write/close实现
$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
…
$ ./mycat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
…

#include<stdio.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>intmain(int argc,char*argv[]){int fd;mode_t mode =0777;
    fd =open(argv[1],O_RDONLY,mode);char ch;int count =read(fd,&ch,sizeof(ch));while(count){printf("%c", ch);
        count =read(fd,&ch,sizeof(ch));}close(fd);return0;}

3. mycp.c

mycp.c的功能与系统cp程序相同
将源文件复制到目标文件,例子如下:
要求使用系统调用open/read/write/close实现
$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
…
$ ./mycp /etc/passwd passwd.bak
$ cat passwd.bak
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
…

#include<stdio.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>intmain(int argc,char*argv[]){mode_t mode =0777;int fd1 =open(argv[1], O_RDONLY, mode);int fd2 =creat(argv[2],mode);char ch;int count =read(fd1,&ch,sizeof(ch));int count2;while(count){
        count2 =write(fd2,&ch,sizeof(ch));
        count =read(fd1,&ch,sizeof(ch));}close(fd1);close(fd2);return0;}

4. mysys.c

mysys的功能与系统函数system相同,要求用进程管理相关系统调用自己实现一遍
使用fork/exec/wait系统调用实现mysys
不能通过调用系统函数system实现mysys
测试程序
#include <stdio.h>

void mysys(char *command)
{
 实现该函数,该函数执行一条命令,并等待该命令执行结束
}

int main()
{
 printf(“--------------------------------------------------\n”);
 mysys(“echo HELLO WORLD”);
 printf(“--------------------------------------------------\n”);
 mysys(“ls /”);
 printf(“--------------------------------------------------\n”);
 return 0;
}
测试程序的输出结果
--------------------------------------------------
HELLO WORLD
--------------------------------------------------
bin core home lib mnt root snap tmp vmlinuz
boot dev initrd.img lost+found opt run srv usr vmlinuz.old
cdrom etc initrd.img.old media proc sbin sys var
--------------------------------------------------

#include<stdio.h>#include<unistd.h>#include<string.h>#include<sys/wait.h>#include<stdlib.h>voidmysys(char*command){int pid;
    pid =fork();if(pid==0){int i=0;char a[5][20];int num =0;int j=0;while(command[i]!='\0'){if(command[i]!=' '){
                a[num][j++]= command[i];}else{
                a[num++][j++]='\0';
                j=0;}
            i++;}
        a[num][j++]='\0';int error;char*argv[5];for(i=0;i<=num;i++){
            argv[i]=(char*)malloc(sizeof(char)*20);strcpy(argv[i],a[i]);}
        argv[i]=NULL;
        error =execvp(argv[0],argv);if(error<0)perror("execv");}wait(NULL);}intmain(){printf("--------------------------------------------------\n");mysys("echo HELLO WORLD");printf("--------------------------------------------------\n");mysys("ls /");printf("--------------------------------------------------\n");return0;}

5. sh1.c

该程序读取用户输入的命令,调用函数mysys(上一个作业)执行用户的命令,示例如下
# 编译sh1.c
$ cc -o sh1 sh1.c

# 执行sh1
$ ./sh

# sh1打印提示符>,同时读取用户输入的命令echo,并执行输出结果
> echo a b c
a b c

# sh1打印提示符>,同时读取用户输入的命令cat,并执行输出结果
> cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
实现内置命令cd、pwd、exit

#include<stdio.h>#include<unistd.h>#include<string.h>#include<sys/wait.h>#include<stdlib.h>intmain(){while(1){printf("%s","> ");char str[105];fgets(str,100,stdin);int i=0;while(str[i]!='\n')
            i++;
        str[i]='\0';
        
        i=0;char a[5][20];int num =0;int j=0;while(str[i]!='\0'){if(str[i]!=' '){
                a[num][j++]= str[i];}else{
                a[num++][j++]='\0';
                j=0;}
            i++;}
        a[num][j++]='\0';int error;char*argv[5];for(i=0;i<=num;i++){
            argv[i]=(char*)malloc(sizeof(char)*20);strcpy(argv[i],a[i]);}
        argv[i]=NULL;if(strcmp(argv[0],"cd")==0){chdir(argv[1]);}elseif(strcmp(argv[0],"exit")==0){exit(0);}elseif(strcmp(argv[0],"pwd")==0){char work_dir[80];getcwd(work_dir,sizeof(work_dir));printf("%s\n",work_dir);}else{int pid;
            pid =fork();if(pid==0){
                error =execvp(argv[0],argv);if(error<0)perror("execv");}wait(NULL);}}return0;}

job4

1. myls.c

myls.c的功能与系统ls程序相同
opendir readdir closedir
在命令行中输入 man opendir 获取帮助
列出指定目录下的文件,例子如下:
$ ./myls job4/test
a
b
c
列出当前目录下的文件,例子如下:
$ cd job4/test
$ ./myls
a
b
c

#include<stdio.h>#include<dirent.h>#include<unistd.h>#include<string.h>intmain(int argc,char*argv[]){
    DIR *dir;if(argc >=2)
        dir =opendir(argv[1]);else
        dir =opendir(getcwd(NULL,0));while(1){structdirent*de =readdir(dir);if(de ==NULL)break;if(strcmp(de->d_name,"..")!=0&&strcmp(de->d_name,".")!=0){printf("%s\n",de->d_name);}}closedir(dir);return0;}

2. mytree.c

mytree.c的功能与系统tree程序相同
使用空格作为缩进,表示层次
$ ./mytree job4/test
test
 a
 b
 x
 y
 z
c

#include<stdio.h>#include<dirent.h>#include<unistd.h>#include<string.h>#include<stdlib.h>voidmytree(int k_num,char*work_dir){char k[80]="";for(int i=0;i<k_num;i++)strcat(k," ");
    DIR *dir =opendir(work_dir);if(dir ==NULL){perror("opendir");exit(0);}while(1){structdirent*de =readdir(dir);if(de ==NULL)break;if(strcmp(de->d_name,"..")!=0&&strcmp(de->d_name,".")!=0){printf("%s",k);printf("%s\n", de->d_name);if(de->d_type == DT_DIR){strcat(work_dir,"/");strcat(work_dir,de->d_name);mytree(k_num+1,work_dir);}}}closedir(dir);}intmain(int argc,char*argv[]){if(argc >=2){printf("%s\n",argv[1]);mytree(1, argv[1]);}else{printf("%s\n",getcwd(NULL,0));mytree(1,getcwd(NULL,0));}return0;}

job5

1.sh2.c

实现shell程序,要求在第1版的基础上,增加文件重定向功能
重定向输入
重定向输出
重定向追加

#include<stdio.h>#include<unistd.h>#include<string.h>#include<sys/wait.h>#include<sys/stat.h>#include<fcntl.h>#include<stdlib.h>voidchild(char*argv[]){int num=0;int i =0;while(argv[i]){
        i++;
        num++;}char str1[80];char str2[80];if(argv[1]!=NULL&& argv[1][0]=='<'){memcpy(str1, argv[1]+1,sizeof(argv[1]-1));int fd1 =open(str1,O_CREAT|O_RDWR,0666);dup2(fd1,0);//input from fd1;close(fd1);
        argv[1]=NULL;//for cat}if(argv[2]!=NULL&& argv[2][0]=='>'){int fd2;if(argv[2][1]=='>'){// >>memcpy(str2,argv[2]+2,sizeof(argv[2]-2));
            fd2 =open(str2,O_CREAT|O_RDWR|O_APPEND,0666);}else{// >    memcpy(str2,argv[2]+1,sizeof(argv[2]-1));
            fd2 =open(str2,O_CREAT|O_RDWR|O_TRUNC,0666);}dup2(fd2,1);//output into fd2;close(fd2);
        argv[2]=NULL;//for echo}int error =execvp(argv[0],argv);if(error<0)perror("execv");}intmain(){while(1){printf("%s","> ");char str[105];fgets(str,100,stdin);int i=0;while(str[i]!='\n')
            i++;
        str[i]='\0';
        
        i=0;char a[5][20];int num =0;int j=0;while(str[i]!='\0'){if(str[i]!=' '){
                a[num][j++]= str[i];}else{
                a[num++][j++]='\0';
                j=0;}
            i++;}
        a[num][j++]='\0';int error;char*argv[5];for(i=0;i<=num;i++){
            argv[i]=(char*)malloc(sizeof(char)*20);strcpy(argv[i],a[i]);}
        argv[i]=NULL;if(strcmp(argv[0],"cd")==0){chdir(argv[1]);}elseif(strcmp(argv[0],"exit")==0){exit(0);}elseif(strcmp(argv[0],"pwd")==0){char work_dir[80];getcwd(work_dir,sizeof(work_dir));printf("%s\n",work_dir);}else{int pid;
            pid =fork();if(pid==0){child(argv);}wait(NULL);}}return0;}

job7

1. pi1.c

使用2个线程根据莱布尼兹级数计算PI

莱布尼兹级数公式: 1 - 1/3 + 1/5 - 1/7 + 1/9 - … = PI/4
主线程创建1个辅助线程
主线程计算级数的前半部分
辅助线程计算级数的后半部分
主线程等待辅助线程运行結束后,将前半部分和后半部分相加

#include<stdio.h>#include<pthread.h>#include<stdlib.h>int count =1e7;typedefstruct{double sum;}result;void*compute(){double sum =0;for(int i=count/2;i<count;i++){if(i&1)//sub
            sum -=(1.0/(i*2+1));else//sub
            sum +=(1.0/(i*2+1));}
    result *res;
    res =malloc(sizeof(result));
    res->sum = sum;return res;}intmain(){pthread_t compute_tid;pthread_create(&compute_tid,NULL, compute,NULL);double sum=0;for(int i=0;i<count/2;i++){if(i&1)//sub
            sum -=(1.0/(i*2+1));else//add
            sum +=(1.0/(i*2+1));}
    result *res;pthread_join(compute_tid,(void**)&res);//wait compute finished
    sum =(sum + res->sum)*4;printf("%.7lf\n",sum);return0;}

2. pi2.c

使用N个线程根据莱布尼兹级数计算PI

与上一题类似,但本题更加通用化,能适应N个核心
主线程创建N个辅助线程
每个辅助线程计算一部分任务,并将结果返回
主线程等待N个辅助线程运行结束,将所有辅助线程的结果累加
本题要求 1: 使用线程参数,消除程序中的代码重复
本题要求 2: 不能使用全局变量存储线程返回值

解决思路:
该题主要考查N个线程的创建与运行,首先需要在主线程中创建N个辅助线程,需要通过结构体完成主线程与子线程之间的数值交互,由于需要每个线程完成一部分计算任务,所以需要确定计算的开始和结束位置。主线程等待所有子线程都计算完后将其返回值累加。

#include<stdio.h>#include<pthread.h>#include<stdlib.h>int N =4;int count =1e7;typedefstruct{//return the resultdouble sum;}result;typedefstruct{//connect main_thread and child_threadint start;int end;}param;void*compute(void*arg){double sum=0;
    param *par;
    par =(param *)arg;for(int i=par->start;i<par->end;i++){if(i&1)//sub
            sum -=(1.0/(i*2+1));else//add
            sum +=(1.0/(i*2+1));}
    result *res;// return the result
    res =malloc(sizeof(result));
    res->sum = sum;return res;}intmain(){pthread_t computers[N];int i;
    param pars[N];for(i=0;i<N;i++){// create the child threads
        param *par;
        par =&pars[i];
        par->start =(count/N)* i;
        par->end =(count/N)*(i+1);pthread_create(&computers[i],NULL, compute, par);}
    result *res[N];for(i=0;i<N;i++)// wait the child threadspthread_join(computers[i],(void**)&res[i]);double sum =0;for(i=0;i<N;i++)
        sum += res[i]->sum;// add the resultprintf("%.7lf\n",sum*4);return0;}

3. sort.c

多线程排序
主线程创建两个辅助线程
辅助线程1使用选择排序算法对数组的前半部分排序
辅助线程2使用选择排序算法对数组的后半部分排序
主线程等待辅助线程运行結束后,使用归并排序算法归并子线程的计算结果
本题要求 1: 使用线程参数,消除程序中的代码重复

#include<stdio.h>#include<stdlib.h>#include<pthread.h>int array[]={5,9,1,3,6,7,2,10,4,8};#defineN2#definenum10int temp[num];structparam{int*array;int start;int end;};structresult{int*array;};void*selection_sort(void*arg){structparam*param;structresult*result;int sum =0;
    param =(structparam*)arg;int i,j,min,temp;for(i=param->start;i<param->end-1;i++){    
        min = i;for(j=i+1;j<param->end;j++){if(param->array[j]<param->array[min])
                min = j;}if(min!=i){
            temp = param->array[min];
            param->array[min]= param->array[i];
            param->array[i]= temp;}}
    result =malloc(sizeof(structresult));
    result->array = param->array;return result;}voidmerge_sort(int a[],int l,int r){int mid;if( l >= r)return;
    mid =(l+r)/2;merge_sort(a,l,mid);merge_sort(a,mid+1,r);int i = l, j = mid +1;int k =0;while(i<=mid && j<=r){if(a[i]<=a[j])
            temp[k++]= a[i++];else
            temp[k++]= a[j++];}while(i<=mid) temp[k++]= a[i++];while(j<=r) temp[k++]= a[j++];for(i=l,j=0;i<=r;i++,j++)
        a[i]= temp[j];}intmain(){pthread_t workers[N];structparam params[N];for(int i=0;i<N;i++){structparam*param;
        param  =&params[i];
        param->array = array;
        param->start = i *(num/N);
            param->end =(i+1)*(num/N);pthread_create(&workers[i],NULL, selection_sort, param);}for(int i=0;i<N;i++){structresult*result;pthread_join(workers[i],(void**)&result);free(result);}// finish selection_sortmerge_sort(array,0,num-1);for(int i=0;i<num;i++)printf("%d ",array[i]);printf("\n");return0;}

job8

1. pc.c

使用条件变量解决生产者、计算者、消费者问题

  • 系统中有3个线程:生产者、计算者、消费者
  • 系统中有2个容量为4的缓冲区:buffer1、buffer2
  • 生产者 - 生产’a’、‘b’、‘c’、‘d’、‘e’、‘f’、‘g’、'h’八个字符- 放入到buffer1- 打印生产的字符
  • 计算者 - 从buffer1取出字符- 将小写字符转换为大写字符,按照 input:OUTPUT 的格式打印- 放入到buffer2
  • 消费者 - 从buffer2取出字符- 打印取出的字符
  • 程序输出结果(实际输出结果是交织的) a b c … a:A b:B c:C … A B C …

解决思路:
此题为课上讲的生产者消费者例子的扩充,等于完成2次生产消费关系。我在第一次做的时候直接将所有的函数及变量都区别了1和2,produce和compute对应为1,compute和consume对应为2,直接照搬课上的例子就可以实现,但是在最后复习的时候搞懂了其中的原理,发现这么写有很多相同的代码片段,一点儿都不简洁,所以用数组和下标实现了相对简洁的代码。
此题首先要创建3个线程,分别代表生产者、计算者、消费者,在生产者中存存数据到第一个buffer里,在计算者中取出生产者存放的数据,并将变化后的结构存入第二个buffer里,在消费者从第二个buffer里取出数据。这里的存取数据中封装了条件变量,实现存取的原子性,减少不必要的控制错误。

#include<stdio.h>#include<pthread.h>#defineCAPACITY4#defineITEM_COUNT(CAPACITY*2)int buffer1[CAPACITY];int buffer2[CAPACITY];int in[2],out[2];pthread_mutex_t mutex[2];pthread_cond_t wait_empty_buffer[2];pthread_cond_t wait_full_buffer[2];intbuffer_is_empty(int i){return(in[i]==out[i]);}intbuffer_is_full(int i){return(((in[i]+1)% CAPACITY)== out[i]);}voidput_item(int i,int item){pthread_mutex_lock(&mutex[i]);while(buffer_is_full(i))pthread_cond_wait(&wait_empty_buffer[i],&mutex[i]);if(i==0){//put item
        buffer1[in[i]]= item;}else
        buffer2[in[i]]= item;
    in[i]=(in[i]+1)%CAPACITY;pthread_cond_signal(&wait_full_buffer[i]);pthread_mutex_unlock(&mutex[i]);}intget_item(int i){int item;pthread_mutex_lock(&mutex[i]);//let the mutex and cond in the get_itemwhile(buffer_is_empty(i))//prevent some errorspthread_cond_wait(&wait_full_buffer[i],&mutex[i]);if(i==0)
        item = buffer1[out[i]];//get itemelse
        item = buffer2[out[i]];

    out[i]=(out[i]+1)% CAPACITY;pthread_cond_signal(&wait_empty_buffer[i]);pthread_mutex_unlock(&mutex[i]);return item;}void*produce(){int item ='a';for(int i=0;i<ITEM_COUNT;i++){printf("%c\n",item);put_item(0,item);
        item++;}}void*compute(){int item;for(int i=0;i<ITEM_COUNT;i++){
        item =get_item(0);printf("    %c:",item);
        item = item -32;put_item(1,item);printf("%c\n",item);}}void*consume(){int item;for(int i=0;i<ITEM_COUNT;i++){
        item =get_item(1);printf("         %c\n",item);}}intmain(){pthread_t producer,computer,consumer;int i;for(i=0;i<2;i++){//initpthread_mutex_init(&mutex[i],NULL);pthread_cond_init(&wait_empty_buffer[i],NULL);pthread_cond_init(&wait_full_buffer[i],NULL);}//create the sub threadspthread_create(&producer,NULL, produce,NULL);pthread_create(&computer,NULL, compute,NULL);pthread_create(&consumer,NULL, consume,NULL);//wait the sub threads finishedpthread_join(producer,NULL);pthread_join(computer,NULL);pthread_join(consumer,NULL);return0;}

2. pp.c

使用条件变量实现 ping-pong 问题

  • 系统中有2个线程:ping 线程和 pong 线程
  • ping 线程先执行
  • ping 线程执行流程如下 1. 打印输出 ping2. 等待 pong 线程输出3. 执行第 1 步
  • pong 线程执行流程如下 1. 打印输出 pong2. 等待 ping 线程输出3. 执行第 1 步
  • 程序输出结果 ping pong ping pong …
#include<stdio.h>#include<pthread.h>pthread_mutex_t mutex;pthread_cond_t wait_ping,wait_pong;int state =1;void*ping(){int count=0;while(count++<20){pthread_mutex_lock(&mutex);while(state!=1)pthread_cond_wait(&wait_ping,&mutex);printf("ping\n");
        state =0;pthread_cond_signal(&wait_pong);pthread_mutex_unlock(&mutex);}}void*pong(){int count=0;while(count++<20){pthread_mutex_lock(&mutex);while(state!=0)pthread_cond_wait(&wait_pong,&mutex);printf("pong\n");
        state =1;pthread_cond_signal(&wait_ping);pthread_mutex_unlock(&mutex);}}intmain(){pthread_t ping_tid,pong_tid;pthread_mutex_init(&mutex,NULL);pthread_cond_init(&wait_ping,NULL);pthread_cond_init(&wait_pong,NULL);pthread_create(&ping_tid,NULL, ping,NULL);pthread_create(&pong_tid,NULL, pong,NULL);pthread_join(ping_tid,NULL);pthread_join(pong_tid,NULL);return0;}

job9

1. pc.c

使用信号量解决生产者、计算者、消费者问题
功能与 job8/pc.c 相同

解决思路:
使用信号量达到封装的效果,定义信号量的等待和释放函数,等待的过程将信号量的值减一,释放的过程将信号量的值加一,用来判断当前状态是否可用,如果该值小于等于0,那需要一直等待信号量才可以进行下一步操作。
对于此题需要先初始化信号量,创建生产者、计算者、消费者线程。在子线程里,需要先等待信号量,在执行完相应的操作后再释放信号量,允许其它线程进行执行。

#include<stdio.h>#include<pthread.h>#include<unistd.h>#defineCAPACITY4int buffer1[CAPACITY];int in1;int out1;int buffer2[CAPACITY];int in2;int out2;intbuffer1_is_empty(){return in1 == out1;}intbuffer1_is_full(){return(in1 +1)% CAPACITY == out1;}intbuffer2_is_empty(){return in2 == out2;}intbuffer2_is_full(){return(in2 +1)% CAPACITY == out2;}intget_item1(){int item1;
    item1 = buffer1[out1];
    out1 =(out1 +1)% CAPACITY;return item1;}intget_item2(){int item2;
    item2 = buffer2[out2];
    out2 =(out2 +1)% CAPACITY;return item2;}voidput_item1(int item1){
    buffer1[in1]= item1;
    in1 =(in1 +1)% CAPACITY;}voidput_item2(int item2){
    buffer2[in2]= item2;
    in2 =(in2 +1)% CAPACITY;}typedefstruct{int value;pthread_mutex_t mutex;pthread_cond_t cond;}sema_t;voidsema_init(sema_t*sema,int value){
    sema->value = value;pthread_mutex_init(&sema->mutex,NULL);pthread_cond_init(&sema->cond,NULL);}voidsema_wait(sema_t*sema){pthread_mutex_lock(&sema->mutex);while(sema->value <=0)pthread_cond_wait(&sema->cond,&sema->mutex);
    sema->value --;pthread_mutex_unlock(&sema->mutex);}voidsema_signal(sema_t*sema){pthread_mutex_lock(&sema->mutex);++ sema->value;pthread_cond_signal(&sema->cond);pthread_mutex_unlock(&sema->mutex);}sema_t mutex1_sema;sema_t empty_buffer1_sema;sema_t full_buffer1_sema;sema_t mutex2_sema;sema_t empty_buffer2_sema;sema_t full_buffer2_sema;#defineITEM_COUNT(CAPACITY*2)void*consume(void*arg){int i;int item2;for(i=0;i<ITEM_COUNT;i++){sema_wait(&full_buffer2_sema);sema_wait(&mutex2_sema);

        item2 =get_item2();printf("        %c\n", item2);sema_signal(&mutex2_sema);sema_signal(&empty_buffer2_sema);}returnNULL;}void*compute(){int i;int item1;int item2;for(i=0;i<ITEM_COUNT;i++){//readsema_wait(&full_buffer1_sema);sema_wait(&mutex1_sema);

        item1 =get_item1();
        item2 = item1 -32;printf("    %c:%c\n",item1,item2);sema_signal(&mutex1_sema);sema_signal(&empty_buffer1_sema);//writesema_wait(&empty_buffer2_sema);sema_wait(&mutex2_sema);put_item2(item2);sema_signal(&mutex2_sema);sema_signal(&full_buffer2_sema);}returnNULL;}void*produce(){int i;int item1;for(i=0;i<ITEM_COUNT;i++){sema_wait(&empty_buffer1_sema);sema_wait(&mutex1_sema);

        item1 = i +'a';put_item1(item1);printf("%c\n", item1);sema_signal(&mutex1_sema);sema_signal(&full_buffer1_sema);}returnNULL;}intmain(){pthread_t consumer_tid;pthread_t computer_tid;sema_init(&mutex1_sema,1);sema_init(&empty_buffer1_sema, CAPACITY-1);sema_init(&full_buffer1_sema,0);sema_init(&mutex2_sema,1);sema_init(&empty_buffer2_sema, CAPACITY-1);sema_init(&full_buffer2_sema,0);pthread_create(&computer_tid,NULL, compute,NULL);pthread_create(&consumer_tid,NULL, consume,NULL);produce();pthread_join(consumer_tid,NULL);pthread_join(computer_tid,NULL);return0;}

2. pp.c

使用信号量实现 ping-pong 问题
功能与 job8/pp.c 相同

#include<stdio.h>#include<pthread.h>#defineCAPACITY4#defineITEM_COUNT(CAPACITY*2)int in[2],out[2];int buffer[2][CAPACITY];typedefstruct{int value;pthread_mutex_t mutex;pthread_cond_t cond;}sema_t;voidsema_init(sema_t* sema,int value){
    sema->value = value;pthread_mutex_init(&sema->mutex,NULL);pthread_cond_init(&sema->cond,NULL);}voidsema_wait(sema_t*sema){pthread_mutex_lock(&sema->mutex);while(sema->value<=0)pthread_cond_wait(&sema->cond,&sema->mutex);
    sema->value--;pthread_mutex_unlock(&sema->mutex);}voidsema_signal(sema_t*sema){pthread_mutex_lock(&sema->mutex);
    sema->value++;pthread_cond_signal(&sema->cond);pthread_mutex_unlock(&sema->mutex);}sema_t mutex_sema[2];sema_t full_buffer[2];sema_t empty_buffer[2];intbuffer_is_empty(int i){return(in[i]==out[i]);}intbuffer_is_full(int i){return((in[i]+1)%CAPACITY == out[i]);}voidput_item(int i,int item){sema_wait(&mutex_sema[i]);sema_wait(&empty_buffer[i]);

    buffer[i][in[i]]= item;
    in[i]=(in[i]+1)% CAPACITY;sema_signal(&full_buffer[i]);sema_signal(&mutex_sema[i]);}intget_item(int i){int item;sema_wait(&mutex_sema[i]);sema_wait(&full_buffer[i]);

    item = buffer[i][out[i]];
    out[i]=(out[i]+1)% CAPACITY;sema_signal(&empty_buffer[i]);sema_signal(&mutex_sema[i]);return item;}void*produce(){int item ='a';for(int i=0;i<ITEM_COUNT;i++){printf("%c\n",item);put_item(0,item);
        item++;}}void*compute(){int item;for(int i=0;i<ITEM_COUNT;i++){
        item =get_item(0);printf("    %c:",item);
        item = item -32;put_item(1, item);printf("%c\n", item);}}void*consume(){int item;for(int i=0;i<ITEM_COUNT;i++){
        item =get_item(1);printf("         %c\n",item);}}intmain(){pthread_t producer,computer,consumer;int i;for(i=0;i<2;i++){sema_t*sema;
        sema =&mutex_sema[i];sema_init(sema,1);
        sema =&empty_buffer[i];sema_init(sema, CAPACITY-1);
        sema =&full_buffer[i];sema_init(sema,0);}pthread_create(&producer,NULL, produce,NULL);pthread_create(&computer,NULL, compute,NULL);pthread_create(&consumer,NULL, consume,NULL);pthread_join(producer,NULL);pthread_join(computer,NULL);pthread_join(consumer,NULL);return0;}

job10

1. sfind.c

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<dirent.h>#include<sys/stat.h>#include<unistd.h>voidfind_file(char*path,char*target){
    FILE *file =fopen(path,"r");char line[256];while(fgets(line,sizeof(line), file)){if(strstr(line, target))printf("%s: %s",path, line);}fclose(file);}voidfind_dir(char*path,char*target){
    DIR *dir =opendir(path);structdirent*entry;while(entry =readdir(dir)){char name[256];strcpy(name, path);if(strcmp(entry->d_name,".")==0)continue;if(strcmp(entry->d_name,"..")==0)continue;if(entry->d_type == DT_DIR){strcat(name,"/");strcat(name,entry->d_name);//        printf("%s\n", name);find_dir(name, target);}if(entry->d_type == DT_REG){strcat(name,"/");strcat(name,entry->d_name);//        printf("111%s\n",name);find_file(name, target);//    printf("file  %s\n", entry->d_name);}}closedir(dir);}intmain(int argc,char*argv[]){if(argc !=3){puts("Usage: sfind file string");return0;}char*path = argv[1];char*string = argv[2];structstat info;stat(path,&info);if(S_ISDIR(info.st_mode))find_dir(path, string);elsefind_file(path, string);return0;}

2. pfind.c

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<dirent.h>#include<sys/stat.h>#include<unistd.h>#include<pthread.h>#defineWORKER_NUMBER4#defineCAPACITY4typedefstruct{int is_end;char path[128];char string[128];}task;

task buffer[CAPACITY];int in;int out;intbuffer_is_empty(){return in==out;}intbuffer_is_full(){return(in+1)%CAPACITY == out;}pthread_mutex_t mutex;pthread_cond_t wait_empty_buffer;pthread_cond_t wait_full_buffer;

task get_task(){
    task item;//    task *buffer;//    buffer = &buffer[out];pthread_mutex_lock(&mutex);while(buffer_is_empty())pthread_cond_wait(&wait_full_buffer,&mutex);

    item.is_end = buffer[out].is_end;strcpy(item.path,buffer[out].path);strcpy(item.string, buffer[out].string);
    out =(out +1)% CAPACITY;pthread_cond_signal(&wait_empty_buffer);pthread_mutex_unlock(&mutex);return item;}voidput_task(task *item){//    task *buffer;//    buffer = &buffer[in];pthread_mutex_lock(&mutex);while(buffer_is_full())pthread_cond_wait(&wait_empty_buffer,&mutex);

    buffer[in].is_end = item->is_end;strcpy(buffer[in].path, item->path);strcpy(buffer[in].string, item->string);
    in =(in +1)% CAPACITY;pthread_cond_signal(&wait_full_buffer);pthread_mutex_unlock(&mutex);}voidfind_file(char*path,char*target){
    FILE *file =fopen(path,"r");char line[256];while(fgets(line,sizeof(line), file)){if(strstr(line, target))printf("%s: %s",path, line);}fclose(file);}void*worker_entry(){while(1){
        task t;
        t =get_task();if(t.is_end)break;find_file(t.path, t.string);}returnNULL;}voidfind_dir(char*path,char*target){
    DIR *dir =opendir(path);structdirent*entry;while(entry =readdir(dir)){char name[256];strcpy(name, path);if(strcmp(entry->d_name,".")==0)continue;if(strcmp(entry->d_name,"..")==0)continue;if(entry->d_type == DT_DIR){strcat(name,"/");strcat(name,entry->d_name);//    printf("%s\n", name);find_dir(name, target);}if(entry->d_type == DT_REG){strcat(name,"/");strcat(name,entry->d_name);
            task item;
            item.is_end =0;strcpy(item.path, name);strcpy(item.string, target);put_task(&item);}}closedir(dir);}intmain(int argc,char*argv[]){if(argc !=3){puts("Usage: sfind file string");return0;}char*path = argv[1];char*string = argv[2];pthread_mutex_init(&mutex,NULL);pthread_cond_init(&wait_empty_buffer,NULL);pthread_cond_init(&wait_full_buffer,NULL);structstat info;stat(path,&info);pthread_t workers[WORKER_NUMBER];for(int i=0;i<WORKER_NUMBER;i++){pthread_create(&workers[i],NULL, worker_entry,NULL);}if(S_ISDIR(info.st_mode)){find_dir(path, string);for(int i=0;i<WORKER_NUMBER;i++){
            task item;
            item.is_end =1;put_task(&item);}}elsefind_file(path, string);for(int i=0;i<WORKER_NUMBER;i++){pthread_join(workers[i],NULL);}return0;}
标签: linux

本文转载自: https://blog.csdn.net/changyana/article/details/125566527
版权归原作者 ChangYan. 所有, 如有侵权,请联系我们删除。

“NUAA操作系统OS实验及上机考试记录”的评论:

还没有评论