我电操作系统上机实验题目(1\2)整理记录

2020-05-10  本文已影响0人  Your7Maxx

最近课少了,实验多了。趁今天下午的机会把操作系统的上机题也解决一下,顺便整理下相关的知识点。

老师还蛮奇葩的,非要搞什么中英文教学。

下面是实验一的内容:

题目的大概意思就是,让我们写一个shell脚本,模拟Linux中的cp命令,也就是拷贝文件的命令,需要进行错误检查(参数检查,程序逻辑,函数返回值判断等),然后又说明了只考虑文件,不考虑目录(简单了点-.-),并且最后用strace命令查看所编写程序执行过程中调用的系统调用。

先看一下,实验一中涉及到的两个命令的基本用法:

cp命令:(摘自菜鸟教程)

strace命令:

     按照strace官网的描述, strace是一个可用于诊断、调试和教学的Linux用户空间跟踪器。我们用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。不难理解,该命令它能够打开应用进程的这个黑盒,通过系统调用的线索,告诉你进程大概在干嘛。

两个比较常用的用法:
1、strace [your commend](在要执行的命令前直接加strace,追踪你的命令的执行过程)

2、strace -p [your commend's pid](跟踪已经在执行的进程,并且不打断。先查看pid:pidof)

实验过程:

根据资料的查询,这里是可以利用两种系统调用来实现cp的功能:
(1)read&write

(2)fread&fwrite

这里采用的是read/write的系统调用:

首先不po代码:(我已经记不得debug了多少次了),先上报错。

报错一:

第一个报错很**,头文件.h忘记加了。

报错二:

warning是隐式声明与内建函数'printf'不兼容,就是缺少‘printf’的库函数头文件<stdio.h>加上。

报错三:

expected declaration or statement,以前码代码的时候经常看见,大部分的原因就是花括号少了或者多了不匹配,这里也是同样的问题。

下面就编译成功了。

在当前目录下创建一个test文件,文件内容'test success!‘。

跑一下看看:./my_cp test /tmp

结果在/tmp目录下发现并没产生任何文件。(喝口wusu冷静一下)

再回头看看源文件,发现缺少关闭文件的代码块(但这不该是上边问题的根源哈),还是先加上了。

在跑一下,无果。

用strace跟踪一下看看:strace ./my_cp test /tmp

红色标注的部分提示Bad file descriptor,google了下相关报错,其中有篇文章这样解释:

Open默认的打开方式是只读,进行写操作时,是不允许的。

但是我的程序并不是对打开文件进行写操作啊??半信半疑的将open的参数改为了O_WRONLY

再重编译,运行,还是一样的结果。

再用strace跟踪看看:

刚才一直认为是写操作出现了问题,然后忽略了上面的报错,open的返回值为-1,说明文件open就失败了,但我命令的/tmp是目录啊!!原来如此,自己给自己设坑了。在一开始还窃喜避开目录的讨论,但是在这里又不自觉地用了目录作为目标地址,很捞。

修改命令 ./my_cp test /temp/test2

复制成功。

再测试下命令输入不符合格式:

代码部分:

实验二:

大致要求就是,自己实现一个shell,然后着重的说明了添加history的特性和相关注意事项。

能力有限,代码也是参考的一个博主的。虽然有点出入,但是大同小异。

编译的时候遇到一个问题:

函数未声明,重写了下这个函数,得以解决。

测试结果:

Ctrl C查看历史命令(history) ||   Ctrl Z 停止

代码

```

include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/shm.h>

#include <wait.h>

#include <string.h>

#include <signal.h>

#define MAX_LINE 80    /* 80 chars per line, per command, should be enough. */

#define BUFFERSIZE 11

typedef struct{

    int number;

    char com[MAX_LINE];

}command;

command buffer[BUFFERSIZE];

int buffer_pointer;

int setup(char inputBuffer[], char *args[],int *background);

void print(){

    int i;

    fflush(stdout);

    write(STDOUT_FILENO,"\n",1);

    for(i = (buffer_pointer - 1) % BUFFERSIZE;\

        i != (buffer_pointer % BUFFERSIZE) && buffer[i].number;\

        i = (i - 1 + BUFFERSIZE) % BUFFERSIZE ){

        printf("%d\t%s",buffer[i].number,buffer[i].com);

        fflush(stdout);

    }

}

void handle_SIGINT(){

    print();

    signal(SIGINT, SIG_IGN);

    return;

}

int setup(char inputBuffer[], char *args[],int *background){

int length, /* # of characters in the command line */

        i,      /* loop index for accessing inputBuffer array */

        start,  /* index where beginning of next command parameter is */

        ct;    /* index of where to place the next parameter into args[] */

pid_t pid;

    ct = 0;

    length = read(STDIN_FILENO, inputBuffer, MAX_LINE);

    start = -1;

    if(length == 0)

        exit(0);

if(length < 0){

args[0] = NULL;

          return 0;

        }

if(inputBuffer[0] == 'r' && (inputBuffer[1] == ' ' || inputBuffer[1] == '\n')){

        if(inputBuffer[1] == '\n'){

            write(STDOUT_FILENO,buffer[(buffer_pointer - 1) % BUFFERSIZE].com,\

                                strlen(buffer[(buffer_pointer - 1) % BUFFERSIZE].com));

            strcpy(inputBuffer,buffer[(buffer_pointer - 1) % BUFFERSIZE].com);

            length = strlen(inputBuffer);

        }

else{

            int j;

            if(!buffer_pointer) return 0;

            for(j = (buffer_pointer - 1) % BUFFERSIZE;\

                j != (buffer_pointer % BUFFERSIZE) && (buffer[j].com[0] != inputBuffer[2]) \

                                                  && buffer[j].number;\

                j = (j - 1 + BUFFERSIZE) % BUFFERSIZE );

            if(j == (buffer_pointer % BUFFERSIZE) || buffer[j].number == 0){

                char NF[15] = "Not found\n";

                write(STDOUT_FILENO,NF,strlen(NF));

                return 0;

            }

            else{

                write(STDOUT_FILENO,buffer[j].com,strlen(buffer[j].com));

strcpy(inputBuffer,buffer[j].com);

                length = strlen(inputBuffer);

            }

        }

    }

    if(inputBuffer[0] != '\n'){

        buffer[(buffer_pointer % BUFFERSIZE)].number = buffer_pointer + 1;

        strcpy(buffer[(buffer_pointer % BUFFERSIZE)].com,inputBuffer);

        buffer_pointer++;

}

for (i = 0;i < length;i++) {

        switch (inputBuffer[i]){

            case ' '  :

            case '\t' :              /* argument separators */

                    if(start != -1){

                args[ct] = &inputBuffer[start];    /* set up pointer */

                        ct++;

                    }

            inputBuffer[i] = '\0'; /* add a null char; make a C string */

                    start = -1;

                    break;

        case '\n':                /* should be the final char examined */

                    if (start != -1){

                args[ct] = &inputBuffer[start];

                        ct++;

                    }

inputBuffer[i] = '\0';

            args[ct] = NULL; /* no more arguments to this command */

                    break;

            default :            /* some other character */

                    if (start == -1)

                        start = i;

            if (inputBuffer[i] == '&'){

                        *background  = 1;

                inputBuffer[i] = '\0';

                    }

            }

    }

    args[ct] = NULL; /* just in case the input line was > 80 */

    return 1;

}

int main(void){

    buffer_pointer = 0;

    memset(buffer, 0, sizeof(buffer));

    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */

    int background;            /* equals 1 if a command is followed by '&' */

    char *args[MAX_LINE/2 + 1];  /* command line (of 80) has max of 40 arguments */

    pid_t pid;

    char com[20] = "osh> ";

    while (1){            /* Program terminates normally inside setup */

background = 0;

            memset(inputBuffer,0,MAX_LINE);

            write(STDOUT_FILENO,com,strlen(com));

        setup(inputBuffer,args,&background);      /* get next command */

        struct sigaction handler;

        handler.sa_handler = handle_SIGINT;

        sigaction(SIGINT,&handler,NULL);

            /* the steps are:

            (1) fork a child process using fork()

            (2) the child process will invoke execvp()

            (3) if background == 0, the parent will wait,

                otherwise returns to the setup() function. */

                pid = fork();

                if(pid < 0){

                    fprintf(stderr,"Fork Failed");

                    exit(-1);

                }

                else if(pid == 0){execvp(args[0],args);exit(0);}

                else if(!background) wait(NULL);

    }

    return 0;

}

```

上一篇 下一篇

猜你喜欢

热点阅读