操作系统实践报告.docx
《操作系统实践报告.docx》由会员分享,可在线阅读,更多相关《操作系统实践报告.docx(33页珍藏版)》请在冰豆网上搜索。
操作系统实践报告
操作系统实践报告
多进程题目
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;jstructresult*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;imin=i;
for(j=i;jif(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;ia[i]=array[i];
b[i]=array[i+LEN/2];
}
/*for(i=0;iprintf("%d\n",a[i]);
}*/
inttm=0;
intti=0,tj=0;
while(tiif(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;titmin=ti;
for(tj=ti;tjif(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;iprintf("%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