操作系统实践报告.docx

上传人:b****4 文档编号:27084147 上传时间:2023-06-26 格式:DOCX 页数:33 大小:21.98KB
下载 相关 举报
操作系统实践报告.docx_第1页
第1页 / 共33页
操作系统实践报告.docx_第2页
第2页 / 共33页
操作系统实践报告.docx_第3页
第3页 / 共33页
操作系统实践报告.docx_第4页
第4页 / 共33页
操作系统实践报告.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

操作系统实践报告.docx

《操作系统实践报告.docx》由会员分享,可在线阅读,更多相关《操作系统实践报告.docx(33页珍藏版)》请在冰豆网上搜索。

操作系统实践报告.docx

操作系统实践报告

操作系统实践报告

多进程题目

sh1.c:

实现shell程序,要求具备如下功能

思路:

 

支持命令参数

$echoarg1arg2arg3

$ls/bin/usr/bin/home实现内置命令cd、pwd、exit

$cd/bin

$pwd

/bin

说明:

首先设置一个死循环模仿shell终端,读取用户的输入,并且根据空格将输入拆分成字符串数组,然后调用excute这个子函数进行处理。

1.echo

根据数组第一个元素来判断命令是什么,判断出是ehco后,fork一个新的进程,将其后的内容一个个输出出来,并且父进程等待子进程退出后再执行,确保输出在屏幕上时不被打断。

2.ls

读取用户输入并且根据拆分的数组判断出是ls命令后,fork一个新的进程,调用execlp函数将/bin/ls下的ls程序装入子进程并将拆分的数组参数部分传递给ls即可,同样的,父进程等待子进程退出,确保输出在屏幕上不被打断。

3.cd

同样是根据输入并拆分成数组后判断出是cd命令后,fork一个新的进程,然后调用chdir并将拆分数组的参数部分传递给chdir作为实参即可。

4.pwd

同样是根据输入并拆分成数组后判断出是pwd命令后,fork一个新的进程,然后调用system("pwd")即可,此命令也可以用来验证上面的cd命令是否正确执行。

5.exit

根据用户输入逼格拆分的数组判断出是exit命令后,excute子函数返回-1,在循环中检测excute的返回值,如果是-1则直接return,退出模仿的shell终端。

sh2.c:

实现shell程序,要求在第1版的基础上,添加如下功能

思路:

 

实现文件重定向$echohello>log

$catlog

Hello

接sh1.c的描述,若判断出是echo命令后,要再次判断拆分的字符串数组中有无“>”出现,如果有,则把“>”之前、echo之后的内容作为输出,把“>”之后到“>”之后的第一个空白字符作为文件名,fopen创建文件并fwrite将输出内容输出到该文件中,并关闭文件。

sh1.c和sh2.c的源代码:

#include

#include

#include

#include

#include

#include

#include

#defineLEN256

#defineWIDTH256

#defineHEIGHT10

voidsplit(charsource[],chardest[HEIGHT][WIDTH])

{

char*p;

p=strsep(&source,"");

inti=0;

for(i=0;p[i]!

='\0';i++){

dest[0][i]=p[i];

}

dest[0][i]='\0';

intj=1;

while(p){

p=strsep(&source,"");

if(p){

for(i=0;p[i]!

='\0';i++){

dest[j][i]=p[i];

}

dest[j][i]='\0';

j++;

}

}

}

intexecute(charcomm[HEIGHT][WIDTH])

{

if(strcmp(comm[0],"echo")==0){

intpid=fork();

if(pid==0){

inti=0;

intis=0;

for(i=1;comm[i][0]!

='\0';i++){

if(comm[i][0]=='>'){

is=1;

break;

}

}

if(is==1){

puts(comm[i+1]);

FILE*fp=fopen(comm[i+1],"w+");

intj=0;

for(j=1;j

fseek(fp,0,SEEK_END);

fwrite(comm[j],strlen(comm[j]),1,fp);

}

fclose(fp);

}else{

intj=0;

for(j=1;comm[j][0]!

='\0';j++){

printf("%s",comm[j]);

printf("");

}

printf("\n");

}

}else{

intstatus;

wait(&status);

}

}elseif(strcmp(comm[0],"ls")==0){

intpid=fork();

if(pid==0){

if(comm[1][0]=='\0'){

execlp("/bin/ls","ls","./",NULL,NULL,NULL);

}else{

execlp("/bin/ls","ls",comm[1],NULL,NULL,NULL);

}

}else{

intstatus;

wait(&status);

}

}elseif(strcmp(comm[0],"cd")==0){

intpid=fork();

if(pid==0){

chdir(comm[1]);

}else{

intstatus;

wait(&status);

}

}elseif(strcmp(comm[0],"pwd")==0){

intpid=fork();

if(pid==0){

system("pwd");

}else{

intstatus;

wait(&status);

}

}elseif(strcmp(comm[0],"exit")==0){

return-1;

}

return1;

}

intmain()

{

while

(1){

charcommand[LEN];

charsplitArray[HEIGHT][WIDTH]={{'\0'}};

printf("%s",">>");

gets(command);

split(command,splitArray);

inti=0;

if(-1==execute(splitArray)){

return0;

}

}

}

sh3.c:

实现shell程序,要求在第2版的基础上,添加如下功能

思路:

 

实现管道

$cat/etc/passwd|wc-l

实现管道和文件重定向

$catinput.txt

3

2

1

3

2

1

$catoutput.txt$catoutput.txt

1

2

3

首先读取用户输入,以“|”为分隔符将输入分割成字符串数组,然后在一个while循环中依次执行下面的动作:

代码中通过pipe()函数来创建管道,创建之后父进程和子进程一个只能向管道写内容,一个只能向管道读内容。

然后利用dup()函数来把进程的输入流或者输出流重定向到管道里,这样就能实现管道的操作。

实现的时候注意可以使用多个“|”来迭代进行管道操作,需要使用一个循环来处理。

用system执行每一条命令,同时还要注意最后一个操作的输出流是标准输出(即屏幕),不需要重定向到管道里,需要特殊处理一下。

源代码:

#include

#include

#include

#include

#include

#include

#include

#defineLEN256

#defineWIDTH256

#defineHEIGHT10

voidsplit(charsource[],chardest[HEIGHT][WIDTH])

{

char*p;

p=strsep(&source,"|");

inti=0;

for(i=0;p[i]!

='\0';i++){

dest[0][i]=p[i];

}

dest[0][i]='\0';

intj=1;

while(p){

p=strsep(&source,"|");

if(p){

for(i=0;p[i]!

='\0';i++){

dest[j][i]=p[i];

}

dest[j][i]='\0';

j++;

}

}

}

main(){

charcommand[LEN];

charsplitArray[HEIGHT][WIDTH]={{'\0'}};

printf("%s",">>");

gets(command);

split(command,splitArray);

inti=0;

for(i=0;splitArray[i][0]!

='\0';i++){

puts(splitArray[i]);

}

intp[2];

pipe(p);

intj=0;

for(j=0;splitArray[j+1][0]!

='\0';j++){

if(fork()==0){

//Childprocess

close(0);

close(p[0])

close(p[1]);

dup(p[0]);

system(splitArray[j]);

}else{

//Parentprocess

close

(1);

close(p[0])

close(p[1]);

dup(p[1]);

system(splitArray[j+1]);

}

}

}

多线程题目

pi1.c:

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

 

莱布尼兹级数公式:

1-1/3+1/5-1/7+1/9-...=PI/4主线程创建1个辅助线程

主线程计算级数的前半部分

辅助线程计算级数的后半部分

思路:

主线程等待辅助线程运行結束后,将前半部分和后半部分相加

计算公式前1000项,主线程计算前5000项,子线程计算后5000项,主进程等待子进程结束,通过pthread_join(sub,(void**)&result);的result参数获取子进程计算结果再相加即可。

源代码:

#include

#include

#include

#include

#defineLEN10000

structresult{

floatsum;

};

void*subThread(){

inti;

floatj;

structresult*result;

floatsum1=0,sum2=0,sum=0;

for(i=LEN/2+1;i<=LEN;i++){

j=i;

if(i%2==0){

sum1+=1/(2*j-1);

}

//printf("%f\n",sum2);

if(i%2==1){

sum2+=1/(2*j-1);

}

}

//printf("%f\n",sum1);

sum=sum2-sum1;

//printf("%f\n",sum);

//printf("%f\n",sum);

result=malloc(sizeof(result));

result->sum=sum;

returnresult;

}

intmain(){

inti;

floatj;

floatsum1=0,sum2=0,sum=0;

for(i=1;i<=LEN/2;i++){

j=i;

if(i%2==0){

sum1+=1/(2*j-1);

}

if(i%2==1){

sum2+=1/(2*j-1);

}

}

sum=sum2-sum1;

//printf("%f\n",sum);

pthread_tsub;

pthread_create(&sub,NULL,subThread,NULL);

structresult*result;

pthread_join(sub,(void**)&result);

sum+=result->sum;

printf("%f\n",sum);

return0;

}

pi2.c:

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

思路:

 

与上一题类似,但本题更加通用化,能适应N个核心,需要使用线程参数来实现主线程创建N个辅助线程

每个辅助线程计算一部分任务,并将结果返回

主线程等待N个辅助线程运行结束,将所有辅助线程的结果累加

设计算公式前1000项,读取用户输入的线程数目N,通过pthread_create(&workers[i-1],NULL,compute,myparam);产生N个线程,并且通过myparam设置每一个线程计算的起始项和终止项,通过pthread_join(workers[j],(void**)&myresult);等待每个线程结束并通过result获取结果,将结果相加即可。

源代码:

#include

#include

#include

#include

#defineLEN10000

#defineMAX_WORKERS100

structparam{

intstart;

intend;

};

structresult{

floatsum;

};

void*compute(void*arg){

inti;

floatj;

structparam*myparam;

myparam=(structparam*)arg;

intstart=myparam->start;

intend=myparam->end;

structresult*myresult;

floatsum1=0,sum2=0,sum3=0;

for(i=start;i<=end;i++){

j=i;

if(i%2==0){

sum1+=1/(2*j-1);

}

if(i%2==1){

sum2+=1/(2*j-1);

}

}

myresult=malloc(sizeof(structresult));

myresult->sum=sum2-sum1;

returnmyresult;

}

intmain(){

intthread_num=1;

structparammyparams[MAX_WORKERS+1];

pthread_tworkers[MAX_WORKERS];

printf("pleaseinputthreadnumber:

");

scanf("%d",&thread_num);

inti;

myparams[0].start=0;

myparams[0].end=0;

for(i=1;i<=thread_num-1;i++){

structparam*myparam;

myparam=&myparams[i];

myparam->start=myparams[i-1].end+1;

myparam->end=myparams[i].start+(LEN/thread_num)-1;

pthread_create(&workers[i-1],NULL,compute,myparam);

}

myparams[thread_num].start=myparams[thread_num-1].end+1;

myparams[thread_num].end=LEN;

pthread_create(&workers[thread_num-1],NULL,compute,&myparams[thread_num]);

intj;

floatsum=0;

for(j=0;j

structresult*myresult;

pthread_join(workers[j],(void**)&myresult);

sum+=myresult->sum;

free(myresult);

}

printf("%f\n",sum);

return0;

}

sort.c:

多线程排序

思路:

 

主线程创建一个辅助线程

主线程使用选择排序算法对数组的前半部分排序

辅助线程使用选择排序算法对数组的后半部分排序

主线程等待辅助线程运行結束后,使用归并排序算法归并数组的前半部分和后半部分

主线程排序数组的前半部分,辅助线程排序后半部分,pthread_create(&worker_id,NULL,&sort,&pa);中pa传递的是数组的首地址,主线程等辅助线程结束后,再调用merge将数组合并为有序。

源代码:

#include

#include

#include

#include

#defineLEN10

intarray[LEN]={0,3,8,6,2,9,5,4,1,7};

structparam{

int*arr;

};

void*sort(void*arg){

structparam*mypa;

mypa=(structparam*)arg;

inti=0;

intj=0;

intmin=0;

inttemp=0;

for(i=LEN/2;i

min=i;

for(j=i;j

if(mypa->arr[min]>mypa->arr[j])min=j;

}

temp=mypa->arr[min];

mypa->arr[min]=mypa->arr[i];

mypa->arr[i]=temp;

}

}

voidmerge(){

inti=0;

inta[LEN/2];

intb[LEN/2];

for(i=0;i

a[i]=array[i];

b[i]=array[i+LEN/2];

}

/*for(i=0;i

printf("%d\n",a[i]);

}*/

inttm=0;

intti=0,tj=0;

while(ti

if(a[ti]

array[tm]=a[ti];

ti++;

}else{

array[tm]=b[tj];

tj++;

}

tm++;

}

}

intmain()

{

structparampa;

pa.arr=array;

intti=0,tj=0,tmin=0;

for(ti=0;ti

tmin=ti;

for(tj=ti;tj

if(array[tmin]>array[tj])tmin=tj;

}

inttemp=array[tmin];

array[tmin]=array[ti];

array[ti]=temp;

}

pthread_tworker_id;

pthread_create(&worker_id,NULL,&sort,&pa);

pthread_join(worker_id,NULL);

merge();

inti=0;

for(i=0;i

printf("%d\n",array[i]);

}

}

pc1.c:

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

思路:

 

系统中有3个线程:

生产者、计算者、消费者

系统中有2个容量为4的缓冲区:

buffer1、buffer2

生产者生产'a'、'b'、'c'、‘d'、'e'、'f'、'g'、'h'八个字符,放入到buffer1计算者从buffer1取出字符,将小写字符转换为大写字符,放入到buffer2消费者从buffer2取出字符,将其打印到屏幕上

类似于生产者和消费者,在问题中,生产者、计算者相对应buffer1是生产者、消费者,二者互斥的进入buffer1,并且当buffer1满时,生产者等待,当buffer1空时,且计算值要从中取数据时,

计算者等待。

同理,计算者、消费者相对应buffer2是生产者和消费者,二者互斥的进入buffer2,当buffer2满时,且计算者要向其中放入数据时,计算者应等待,当buffer2空时,消费者应等待。

源代码:

#include

#include

#defineCAPACITY4

intbuffer1[CAPACITY];

intbuffer2[CAPACITY];

intin1;

intout1;

intin2;

intout2;

intbuffer2_is_empty()

{

returnin2==out2;

}

intbuffer2_is_full()

{

return(in2+1)%CAPACITY==out2;

}

intbuffer1_is_empty()

{

returnin1==out1;

}

intbuffer1_is_full()

{

return(in1+1)%CAPACITY==out1;}

intget_item()

{

intitem;

item=buffer2[out2];

out2=(out2+1)%CAPACITY;returnitem;

}

voidput_item(intitem)

{

buffer1[in1]=item;

in1=(in1+1)%CAPACITY;}

intcal_get_item()

{

intitem;

item=buffer1[out1];

out1=(out1+1)%CAPACITY;returnitem;

}

voidcal_put_item(intitem)

{

buffer2[in2]=item;

in2=(in2+1)%CAPACITY;}

pthread_mutex_tmutex1;

pth

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 企业管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1