操作系统作业完全攻略手册
第一次作业鸽了
建议自己百度git怎么用,linux怎么装
第二次作业
这次软工作业主要是完成基本的shell编程,同时在linux下运行并截图
步骤一:完成shell编程(这是网上的代码。。。等大家这次作业都交完了我再放我的代码,讲道理这部分建议自己写,不然大家都一样的就有点尴尬)
注意:更改main函数中的printf(“osh>”);
要改成老师要求的那样
#include<stdio.h>
#include <unistd.h>
#include<string.h>
#include<stdlib.h>
#define MAX_LINE 80
int input(char* str);
int str_to_args(char* str,char* args[],int str_num);
void display_history(int history_front,int history_rear);
void add_history(char* str,int* front,int* rear);
char history[10][MAX_LINE];//history queue
int input(char* str){
char c;
int i = 0;
while((c = getchar())!='\n' && i<MAX_LINE){
str[i] = c;
i++;
}
if(i == MAX_LINE && c != '\n'){//when error
printf("over maximum length!");
return 0;
}
else{
str[i] = 0;
return i;
}
}
int str_to_args(char* str,char* args[],int str_num){
const char s[2] = " ";
int i = 0;
char* temp;
temp = strtok(str,s);
while(temp != NULL){
args[i] = (char*)malloc(strlen(temp));
strcpy(args[i],temp);
i++;
temp = strtok(NULL,s);
}
args[i] = 0;
return i;
}
void display_history(int history_front,int history_rear){
int i;
for(i = history_front;i < history_rear;i++){
printf("%d\t%s\n",history_rear - i,history[i%10]);
}
}
void add_history(char* str,int* front,int* rear){
strcpy(history[*rear % 10],str);//add
*rear = *rear+1;
if(*rear - *front > 10)
*front++;
}
int main(void){
char* args[MAX_LINE/2+1];//execvp's argslist
int should_run = 1;
int args_num = 0;
char str[MAX_LINE];// user input
int str_num;
int history_front = 0;
int history_rear = 0;
int i = 0;
int background = 0;
int pid_status;
while(should_run){
printf("osh>");
fflush(stdout);
str_num = input(str);//get user input
if(str_num == 0){//no input
continue;
}
if(strcmp(str,"exit")== 0){//exit
should_run = 0;
continue;
}
if(strcmp(str,"history") == 0){//display history
display_history(history_front,history_rear);
}
if(strcmp(str,"!!") == 0){//use recent command
if(history_rear != 0){
strcpy(str,history[(history_rear -1) % 10]);
str_num = strlen(str);
}
else{
printf("No commands in history.\n");
}
}
else if(str[0] == '!'){//use history command
if(str[1] <= '0' || str[1] > '9' || (str[1]-'0') > history_rear-history_front){
printf("No such command in history.\n");
}
else if(str[1] == '1'){
if(str[2] == '0')
strcpy(str,history[history_front %10]);
else if(str[2] == 0)
strcpy(str,history[(history_rear-1) %10]);
else
printf("No such command in history.\n");
}
else
strcpy(str,history[history_rear - str[1] + '0' -1]);
}
add_history(str,&history_front,&history_rear);//add to history
args_num = str_to_args(str,args,str_num);
if(strcmp(args[args_num-1],"&") == 0){
background = 1;
args_num--;
args[args_num] = NULL;
}
pid_t pid = fork();
if(pid == 0){
pid_status = execvp(args[0], args);
}
else{
if(background == 1){
printf("%d is running in background %s \n",pid,str);
}
else{
wait(&pid_status);
}
}
background = 0;
}
return 0;
}
步骤二:安装 gcc和vim 在linux 下运行测试
Vim是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。
简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。
安装vim和gcc
安装vim代码
sudo apt-get install vim-gtk
vim教程参考: vim教程
执行后大概如下:
联网并输入密码即可完成安装
安装gcc代码
sudo apt install gcc
一样的操作
用vim生成Shell.c文件
代码如下
vim Shell.c
之后会进入如下界面:
然后按" i “进入插入文本模式,右键复制粘贴将上述代码粘到文本中
按ESC退出该模式
输入” :wq "将文件保存并退出
生成编译文件
gcc Shell.c -o Shell
在linux下编译测试
./Shell
此时我们界面应该如下:
这时我们就可以测试运行我们的代码了
步骤三:使用make编写makefile文件并运行
运行如下代码创建Makefile文件
vim Makefile
将Makefile文件中粘入如下代码(vim操作基本相同)
这是最简单的一种编译方法,详情可以参照make教程
all: Shell
Shell: Shell.c
gcc -o Shell Shell.c
clean:
rm -rf *.o Shell
此时还是进入刚才的界面,与刚才不同的是,这次我们通过调用makefile文件来进行编译
输入如下命令
make
此时我们再运行
./Shell
在相应位置截图即可,git操作不再申明,哪里有问题可以留言
第三次作业
我们更改Makefile为如下内容(以下部分未测试 ,慎用)
all: Test1 Test2
Test1: test1.c
gcc test1.c -lpthread -o test1
Test2: test2.c
gcc test2.c -lpthread -o test2
clean:
rm -rf *.o Test1
在同一文件夹下修改test1.c为如下内容
以下为生产者代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <semaphore.h>
static pthread_mutex_t lock_x;
#define BUFFER_SIZE 100
#define TRUE 1
#define FALSE 0
/* Shared Memory Layout */
/*
* | counter[0] | counter[1] | status | Product[0] | Product[1] |......| Product[99] |
*/
/* FLAGS For communication */
#define STATUS_READY 0
#define STATUS_RUNNING 1
#define STATUS_COMPLETE 2
#define PRODUCER 0
#define CONSUMER 1
struct Product
{
int Id;
char Name[32];
int Value;
};
/* Shared Memory Global Variables */
key_t shmKey;
int shmId;
void *shmPtr;
void shmInit()
{
shmKey = ftok(".", 'x');
shmId = shmget(shmKey, sizeof(int)*3 + sizeof(struct Product) * BUFFER_SIZE, 0666);
if (shmId < 0) {
printf("*** shmget error (consumer) ***\n");
exit(1);
}
printf("Consumer has received a shared memory.\n");
shmPtr = shmat(shmId, NULL, 0);
if ((int) shmPtr == -1) {
printf("*** shmat error (client) ***\n");
exit(1);
}
}
void shmClean()
{
shmdt((void *) shmPtr);
printf("Consumer has detached its shared memory...\n");
printf("Consumer exits...\n");
}
/* Shared Memory Layout */
/*
* | counter[0] | counter[1] | flag[PRODUCER] | flag[CONSUMER] | turn | status | Product[0] | Product[1] |......| Product[99] |
*/
void main(void)
{
pthread_mutexattr_t lock_x;
int ret;
pthread_mutexattr_t mattr;
//ret = pthread_mutexattr_init(&lock_x); /* * resetting to its default value: private */
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&lock_x, &mattr);
struct Product *buffer;
int *counter;
int *status;
int out = 0;
struct Product next_consumed;
shmInit();
counter = (int*)shmPtr;
status = counter + 2;
buffer = (struct Product*)(status + 1);
printf("Counter:%d\t%d\n",counter[0],counter[1]);
printf("Consumer has attached the shared memory...\n");
if( *status == STATUS_READY )
*status = STATUS_RUNNING;
while(TRUE)
{
while( counter[0] == 0 )
;
pthread_mutex_lock(&lock_x);
next_consumed = buffer[ out ];
out = (out + 1) % BUFFER_SIZE;
counter[0]--;
counter[1]--;
printf("Consume the Product:\n\tId:%d\n\tName:%s\n\tValue:%d\n",
next_consumed.Id,
next_consumed.Name,
next_consumed.Value);
if(counter[0] != counter[1])
{
*status = STATUS_COMPLETE;
printf("counter[0]=%d\tcounter[1]=%d\n", counter[0], counter[1]);
break;
}
pthread_mutex_unlock(&lock_x);
}
shmClean();
exit(0);
}
修改test2.c为以下内容
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 100
static pthread_mutexattr_t lock_x;
#define TRUE 1
#define FALSE 0
/* Shared Memory Layout */
/*
* | counter[0] | counter[1] | status | Product[0] | Product[1] |......| Product[99] |
*/
/* FLAGS For communication */
#define STATUS_READY 0
#define STATUS_RUNNING 1
#define STATUS_COMPLETE 2
#define PRODUCER 0
#define CONSUMER 1
struct Product
{
int Id;
char Name[32];
int Value;
};
/* Global Shared Memory Variables */
key_t shmKey;
int shmId;
void *shmPtr;
void shmInit()
{
shmKey = ftok(".", 'x');
shmId = shmget(shmKey, sizeof(int)*3 + sizeof(struct Product) * BUFFER_SIZE, IPC_CREAT | 0666);
if (shmId < 0) {
printf("*** shmget error (server) ***\n");
exit(1);
}
printf("Produce create a buffer of size %d.\n", BUFFER_SIZE);
shmPtr = shmat(shmId, NULL, 0);
if ((int) shmPtr == -1) {
printf("*** shmat error (Producer) ***\n");
exit(1);
}
}
void shmClean()
{
shmdt((void *) shmPtr);
printf("Producer has detached its shared memory...\n");
shmctl(shmId, IPC_RMID, NULL);
printf("Producer has removed its shared memory...\n");
printf("Producer exits...\n");
}
void main(int argc, char *argv[])
{
int ret;
pthread_mutexattr_t mattr;
//ret = pthread_mutexattr_init(&lock_x); /* * resetting to its default value: private */
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&lock_x, &mattr);
struct Product *buffer;
int* counter;
int in = 0;
int* status;
struct Product product;
int productId = 1;
shmInit();
/* Shared Memory Layout */
/*
* | counter[0] | counter[1] | status | Product[0] | Product[1] |......| Product[99] |
*/
counter = (int*)shmPtr;
status = counter + 2;
buffer = (struct Product*)(status + 1);
printf("Initialize shared variables...\n");
counter[0]=0;
counter[1]=0;
*status = STATUS_READY;
while(TRUE)
{
if( *status == STATUS_COMPLETE )
{
printf("Consumer exit.\n");
break;
}
pthread_mutex_lock(&lock_x);
/* produce a new product */
product.Id = productId++;
sprintf(product.Name, "N:%d",product.Id);
product.Value = product.Id;
printf("Produced new product %d\n", product.Id);
while(counter[0] == BUFFER_SIZE)
;
buffer[in] = product;
in = (in + 1) % BUFFER_SIZE;
counter[0] ++;
counter[1] ++;
pthread_mutex_unlock(&lock_x);
}
shmClean();
exit(0);
}
然后执行make
就行了