1、针对5位哲学家就餐问题,采用奇数号哲学家先拿起左边的筷子,再去拿右边的筷子;而偶数号哲学家则用相反的方法,进行解决。假设每位哲学家思考5秒,进餐3秒,给出100秒内每位哲学家进餐的总次数。(25分)
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#include
#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
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
标准答案
实验报告(修订版)