《操作系统》实验设计作业

本文详细解析了5位哲学家就餐问题的并发解决方案,采用不同加锁策略,并计算了每位哲学家100秒内的进餐次数。同时,探讨了通过共享内存和信号量实现进程间通信,以及可变分区管理的内存动态申请与释放。最后,展示了如何统计C文件中关键系统函数调用次数并保存结果。
摘要由CSDN通过智能技术生成

《操作系统》实验设计作业

1、针对5位哲学家就餐问题,采用奇数号哲学家先拿起左边的筷子,再去拿右边的筷子;而偶数号哲学家则用相反的方法,进行解决。假设每位哲学家思考5秒,进餐3秒,给出100秒内每位哲学家进餐的总次数。(25分)

#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include<time.h>
 
#define phi_num 5
#define think_time 5
#define eat_time 3
#define left (phi_id)%phi_num
#define right (phi_id+1)%phi_num

//加锁方式:阻塞加锁,非阻塞加锁,非阻塞加锁+奇偶哲学家取筷子顺序不同
enum lock_way{block_lock,unblock_lock,odd_even} ;
enum lock_way LOCKWAY=odd_even;

pthread_mutex_t mutex[phi_num];
int eat_times[phi_num];
long phi_time[phi_num];

//哲学家思考
void Do_think(int phi_id){
	printf("philosopher %d is thinking now !\n",phi_id);
	sleep(think_time);
}

//哲学家吃饭
void Do_eat(int phi_id){
	printf("philosopher %d is eating now !\n",phi_id);
	sleep(eat_time);
}

//哲学家取筷子
int Do_take_forks(int phi_id){
    //阻塞加锁方式
    if(LOCKWAY==block_lock){
        pthread_mutex_lock(&mutex[left]);
        printf("block_lock philosopher %d fetched left chopstick %d !\n",phi_id,left);
        pthread_mutex_lock(&mutex[right]);
        printf("block_lock philosopher %d fetched right chopstick %d !\n",phi_id,right);
        return 0;

    //非阻塞加锁方式
    }else if(LOCKWAY==unblock_lock){
        //先取左边筷子
        if(pthread_mutex_trylock(&mutex[left])!=0){
            return -1;
        }
        printf("unblock_lock philosopher %d fetched left chopstick %d !\n",phi_id,left);
        //后取右边筷子,如果不成功,放下左边筷子
        if(pthread_mutex_trylock(&mutex[right])!=0){
            pthread_mutex_unlock(&mutex[left]);
            printf("unblock_lock philosopher %d fetch right chopstick %d failed and released left chopstick %d! \n",phi_id,right,left);
            return -1;
        }
        printf("unblock_lock philosopher %d fetched right chopstick %d !\n",phi_id,right);
        return 0;
    
    //非阻塞加锁+奇偶哲学家取筷子顺序不同
    }else if(LOCKWAY==odd_even){
        //偶数哲学家
        if(phi_id%2==0){
            if(pthread_mutex_trylock(&mutex[left])!=0){
                return -1;
            }
            printf("odd_even philosopher %d fetched left chopstick %d !\n",phi_id,left);
            if(pthread_mutex_trylock(&mutex[right])!=0){
                pthread_mutex_unlock(&mutex[left]);
                printf("odd_even philosopher %d fetch right chopstick %d failed and released left chopstick %d! \n",phi_id,right,left);
                return -1;
            }
            printf("odd_even philosopher %d fetched right chopstick %d !\n",phi_id,right);
            return 0;

        //奇数哲学家先取右边筷子,后取左边筷子
        }else{
            if(pthread_mutex_trylock(&mutex[right])!=0){
                return -1;
            }
            printf("odd_even philosopher %d fetched right chopstick %d !\n",phi_id,right);
            if(pthread_mutex_trylock(&mutex[left])!=0){
                pthread_mutex_unlock(&mutex[right]);
                printf("odd_even philosopher %d fetch right chopstick %d failed and released left chopstick %d! \n",phi_id,left,right);
                return -1;
            }
            printf("odd_even philosopher %d fetched left chopstick %d !\n",phi_id,left);
            return 0;
        }
    }
    return -1;
}

//哲学家放筷子
void Do_put_forks(int phi_id){
    pthread_mutex_unlock(&mutex[left]);
    printf("philosopher %d released  left chopstick %d !\n",phi_id,left);
	pthread_mutex_unlock(&mutex[right]);
    printf("philosopher %d released right chopstick %d !\n",phi_id,right);
}

//哲学家吃饭100秒并计数吃饭次数
void *philosopher(void *arg){
    int phi_id=*(int *)arg;
    time_t  start,end;
    start = time(NULL);
    while(1){
		Do_think(phi_id);
		while(Do_take_forks(phi_id)!=0){
            		sleep(0.1);
            		continue;
               }	
	Do_eat(phi_id);
	Do_put_forks(phi_id);
        eat_times[phi_id]++;
        
        end = time(NULL);
        long duration =end - start;
        phi_time[phi_id]=duration;
        if(duration>100) break;
    }
    
    return NULL;
}


int main(int argc, char *argv[]){
	int num;

    //初始化互斥量
    for(num=0;num<phi_num;num++){
		pthread_mutex_init(&mutex[num],NULL);
        eat_times[num]=0;
	}

    //创建哲学家进程
	pthread_t *phi=(pthread_t*)malloc(sizeof(pthread_t)*phi_num);
	int *id=(int *)malloc(sizeof(int)*phi_num);
	for(num=0;num<phi_num;num++){
		id[num]=num;
		pthread_create(&phi[num],NULL,philosopher,(void*)(&id[num]));
	}

    //主线程阻塞,等待哲学家线程
	for(num=0;num<phi_num;num++){
		pthread_join(phi[num],NULL);
	}

    for(num=0;num<phi_num;num++){
        pthread_mutex_destroy(&mutex[num]);//销毁互斥量
        printf("philosopher %d have eated %d times, took %ld seconds !\n",num,eat_times[num],phi_time[num]);
	}


	return 0;
}

2、通过共享内存和信号量实现进程间通信,其中A进程读入指定路径的文件,每次将一行文件信息保存到共享内存中并等待其他进程将数据读走,直至文件结束;B、C进程为父子进程,并发互斥的读取缓冲区信息并显示,然后再将缓冲区清空,直至接收到“quit”后,父子进程相继退出。(25分)

write:

#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<semaphore.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define BUFFERSIZE 4096

int main(int argc,char *argv[]){ 	
   	int shm_id;
   	key_t shm_key;
   	
   	shm_key=ftok("read.c",0);	
   	shm_id=shmget(shm_key,BUFFERSIZE,0666|IPC_CREAT);
   	
	//create the share memory by shmget()
	if(shm_id < 0){
		perror("shmid error\n");
		exit(1);
	}//if
	
	//get the virtual address of this share memory
	char *shm_buf;
	if((shm_buf = shmat(shm_id,0,0)) < (char*)0){
		perror("shmbuffer error!\n");
		exit(1);
	}
	
	//message input
	char message[1024];
	
	//create the semaphore
	sem_t *mutex = sem_open("mutex",O_CREAT,0666,1);
	sem_t *full = sem_open("full",O_CREAT,0666,0);
	sem_t *empty = sem_open("empty",O_CREAT,0666,1);
    
	char c;
	int i;
	printf("shmid = %d\n",shm_id);
 
 
	char path_in[100];
    	FILE *File_in=NULL;
    	while(!File_in){
        	printf("请输入写入文件地址:");
        	scanf("%s",path_in);
        	File_in=fopen(path_in, "rb");
    	}
    	printf("文件打开成功!\n");
    	//fclose(File_in);
 

	while(1){
		i = -1;
		/*
		while((c = getchar()) != '\n'){
				message[++i] = c;
			}//while
		message[++i] = '\0';
		*/
		//memset(message,0,1024);
                int msg_len=fgets(message,1024,File_in);
                /*判断是否已经到文件尾*/
                //printf("1111!\n");	
        	if(!msg_len){
            		fclose(File_in);
            		break;
        	}                            
		//wait the semaphore
		sem_wait(empty);
		sem_wait(mutex);

		//send the message to shm_buf
		sprintf(shm_buf,message);

		//semaphore +1
		sem_post(mutex);
		sem_post(full);
	}//while
	
    	printf("文件发送成功!\n");	
        if(shmdt(shm_buf)==-1)
        	printf("shmdt is fail\n"); 
        	   
        sem_close(mutex);
        sem_close(full);       
        sem_close(empty); 
        //printf("2222!\n");       
        sem_unlink("mutex");
        sem_unlink("full");       
        sem_unlink("empty");           
                    		
	return 0;
}

read:

#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/wait.h>
#include<semaphore.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

#define BUFFERSIZE 4096

int main(int argc,char *argv[]){

   key_t shm_key;
   shm_key=ftok("read.c",0);	
   int shm_id=shmget(shm_key,1024,0666|IPC_CREAT);
   if(shm_id==-1) printf("cread shmid fail!\n");
	
  char *shm_buf;
  //get the share memory address
  if((shm_buf = shmat(shm_id,0,0)) < (char*)0){
	perror("shm_buf error\n");
	exit(1);
   }//if
 
   sem_t *mutex = sem_open("mutex",1);
   sem_t *full  = sem_open("full",0);
   sem_t *empty = sem_open("empty",1);
   int pid = fork();
   if(pid < 0){
  	perror("pid error\n");
   }//if

   else if(pid == 0){
  	while(1){
  	   	//printf("s1111!\n");	
    		//wait the semaphore
		sem_wait(full);
  		sem_wait(mutex);

		printf("son pid %d receive message:%s\n",getpid(),shm_buf);
		//clear the share memory
		if(strncmp(shm_buf,"quit",4)==0) 
		{
			sem_post(mutex);
			sem_post(empty);
			break;
		}		
		strcpy(shm_buf,"");

    		//semaphore +1
		sem_post(mutex);
		sem_post(empty);
   		}//while
   	}//else if
   else{
	while(1){
	   	//printf("p1111!\n");	
		//wait the semaphore
		sem_wait(full);
		sem_wait(mutex);

		printf("parent pid %d receive message:%s\n",getpid(),shm_buf);
		//clear the share memory
		if(strncmp(shm_buf,"quit",4)==0) 
		{
			sem_post(mutex);
			sem_post(empty);
			break;
		}
		strcpy(shm_buf,"");

		//semaphore +1
        	sem_post(mutex);
		sem_post(empty);
	 	}//while
	}//else


	
        sem_close(mutex);
        sem_close(full);  
        sem_close(empty);             
        
        if(shmdt(shm_buf)==-1) printf("shmdt is fail\n"); 
        if(pid!=0){	
        	if(shmctl(shm_id,IPC_RMID,NULL)==-1) printf("shmctl delete error\n"); 
        }
	return 0;
}

1.txt

Hello 95
Linux 85  
test 30  
win 86
quit
quit

3、以可变分区管理实现内存的动态申请与释放,限定最大分区数和存储空间大小,每次操作后显示分区信息。当申请内存时,从中选取满足要求的空闲区,并划出一个分区;当不满足要求或超出分区数限制时,提示分配失败;当释放内存时,回收相应内存区,并合并成一个新的空闲区。(25分)

#include<iostream>

using namespace std;

const int MaxParts = 10;//最大分区数
const int Memsize = 1024;//存储大小

struct Part//分区信息
{
	int startAddress;//开始地址
	int length;//分区长度
	bool free;//是否空闲
	Part *next;//下一个分区
};

struct Distribution//分配信息
{
	bool give;//是否给予空间
	Part *part;//分配的空间
	int errorType;//错误类型 0 无 1 分区数超限 2 请求不能满足
};

Part partFirst;
int countPart;

void init() {//初始化
	partFirst.startAddress = 0;
	partFirst.length = Memsize;
	partFirst.free = true;
	partFirst.next = NULL;
	countPart = 1;
}

/**
* 请求内存空间
* @length 请求的长度
*/
Distribution requestMemory(int length) {
	bool can = false;
	Part *disPart = NULL;
	int errorType = 0;
	Part *temp = &partFirst;
	do {
		if (temp->free && temp->length >= length) {//如果空闲且大于则分配新分区
			if (countPart + 1 > MaxParts) {//到达最大分区限制则分配
				errorType = 1;
				break;
			}
			else {
				countPart++;
			}
			temp->free = false;
			int tempLength = temp->length;
			temp->length = length;
			//把选中的分区划分一部分满足请求,另外一部分插入到其后面
			Part * tempNext = temp->next;
			temp->next = new Part{
				temp->startAddress + temp->length,
				tempLength - length,
				true,
				tempNext
			};
			disPart = temp;
			can = true;
			break;
		}
		else if (temp->free && temp->length == length) {//空闲且等于请求大小则直接分配
			temp->free = false;
			disPart = temp;
			can = true;
			break;
		}
		else {
			temp = temp->next;
		}
	} while (temp != NULL);
	errorType = 2;
	return { can,disPart ,errorType};
}
/**
* 释放分区
* @id 显示的第n个分区
*/
void freePart(int n) {
	int i = 1;
	Part *temp = &partFirst;
	bool free = false;
	do {
		if (i+1 == n && temp->next != NULL) {
			if (temp->next->next != NULL && temp->next->next->free == true) {
				if (temp->free) {//三连
					Part *center = temp->next;
					Part *right = temp->next->next;
					Part *tempNext = temp->next->next->next;
					temp->length += temp->next->length + temp->next->next->length;
					temp->next = tempNext;
					delete center;
					delete right;
				}
				else {//后连
					Part *right = temp->next->next;
					Part *tempNext = temp->next->next->next;
					temp->next->length += temp->next->next->length;
					temp->next->next = tempNext;
					temp->next->free = true;
					delete right;
				}
			}
			else {
				if (temp->free) {//前连
					Part *center = temp->next;
					Part *tempNext = temp->next->next;
					temp->length += temp->next->length;
					temp->next = tempNext;
					delete center;
				}
				else {//独
					temp->next->free = true;
				}
			}
			free = true;
			break;
		}
		temp = temp->next;
		i++;
	} while (temp != NULL);
	if (!free) {
		printf("释放失败,分区未找到.\n");
	}
}

void showParts() {//打印分区信息
	int i = 1;
	Part *temp = &partFirst;
	printf("分区号 开始地址 分区长度 空闲\n");
	do {
		printf("%-6d %-8d %-8d %-4s\n", i, temp->startAddress, temp->length, temp->free ? "是" : "否");
		temp = temp->next;
		i++;
	} while (temp != NULL);
}

void selectMenu() {
	int select;
	int value;
	Distribution ret;
	bool quit = false;
	while (!quit)
	{
		printf("存储管理模拟\n");
		printf("1、申请空间\n");
		printf("2、释放空间\n");
		printf("3、退出\n");
		cin >> select;
		switch (select)
		{
		case 1:
			printf("请输入大小:\n");
			cin >> value;
			ret = requestMemory(value);
			if (ret.give) {
				printf("分配成功.\n");
			}
			else {
				printf("分配失败.\n");
				printf("%s.\n", ret.errorType==1?"分区数达到限制":"该请求目前不能被满足");
			}
			break;
		case 2:
			printf("请输入序号:\n");
			cin >> value;
			freePart(value);
			break;
		case 3:
			quit = true;
			break;
		default:
			break;
		}
		if(!quit)showParts();
	}
}

int main() {
	init();
	showParts();
	selectMenu();
	getchar();
	return 0;
}

4、指定一个文件夹,下面有许多C源程序文件。按要求编写一个shell程序,分别统计每个C文件中printf、open、close、read、write、fork、signal系统函数被调用的次数,并将统计结果保存到一个文件中。(25分)

#!/bin/bash

mkdir -p ../c_result

declare -a arr=("printf"  "open"  "close"  "read"  "write"  "fork"  "signal")

function read_c(){
	for i in ${arr[@]} #遍历字符串
	do
		sum=0		
		for fp in `find $1 -type f -name "*.c"` #找到所有.c文件
		do
			#if [ -f $file ]
			#then
				echo $fp >> $i"_result"
				temp=`grep -o $i $fp | wc -l` #统计字符串个数
				echo "$temp" >> $i"_result"
				sum=$[ $sum + $temp ] #字符串个数求和
			#fi     
		done
		echo "总出现次数:$sum" >> $i"_result"		
		mv $i"_result" ../c_result #转移到c_result目录下
		echo "$i:$sum" >> "final_result"		
	done
	
	mv "final_result" ../c_result		
}
	
read_c $1


标准答案
实验报告(修订版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值