操作系统实验报告

这篇博客详细介绍了操作系统实验的内容,包括myecho、mycat、mycp等实用程序的实现,涉及系统调用如open、read、write、close。还涵盖了mysys函数的实现,模拟系统命令执行,以及sh3.c中如何处理重定向和管道。此外,实验还包括了使用多线程计算PI(pi1.c和pi2.c)和多线程排序(sort.c)。最后讨论了生产者、计算者、消费者问题的解决方案,使用条件变量和信号量。
摘要由CSDN通过智能技术生成

操作系统实验报告

1. myecho.c

1.1. 实验内容

  • myecho.c的功能与系统echo程序相同
  • 接受命令行参数,并将参数打印出来

1.2. 效果展示

myecho$ ./myecho a b c
a b c

1.3. 实验思路和关键代码

读取输入的参数,按顺序输出

int main(int argc, char *argv[])
{
    for (int i = 1; i < argc; i++)
    {
        printf("%s ", argv[i]);
    }
    printf("\n");
    return 0;
}

2. mycat.c

2.1. 实验内容

  • mycat.c的功能与系统cat程序相同
  • mycat将指定的文件内容输出到屏幕
  • 要求使用系统调用open/read/write/close实现

2.2. 效果展示

mycat$ ./mycat mycat.c

//以下显示mycat.c文件的内容

2.3. 实验思路和关键代码

  • 读取参数, 根据参数打开相应文件
    FILE *fp;
    int fsize;
    int fr;
    char *buffer;

    fp = fopen(argv[1], "r");
    if (!fp)
    {
        printf("不能打开该文件\n");
        exit(0);
    }
  • 通过设置文件指针读取文件大小,分配缓冲区
    fseek(fp, 0, SEEK_END);
    fsize = ftell(fp);
    rewind(fp);

    buffer = (char *)malloc((1 + fsize) * sizeof(char));
    if (!buffer)
    {
   
        printf("分配空间失败\n");
        exit(0);
    }
  • 将文件读取到缓冲区并输出
    fr = fread(buffer, 1, fsize, fp);
    if (!fr)
    {
   
        printf("读文件失败\n");
        exit(0);
    }

    printf("%s\n", buffer);

3. mycp.c

3.1. 实验内容

  • mycp.c的功能与系统cp程序相同
  • 将源文件复制到目标文件
  • 要求使用系统调用open/read/write/close实现

3.2. 效果演示

mycp$ ./mycp mycp.c mycp1.c

//将mycp.c的内容复制到了mycp1.c

3.3. 实验思路和关键代码

  • 与2.3.中相同, 不过在将源文件写到缓冲区后, 需要打开/创建目的文件, 将缓冲区内容写到目的文件
    fp = fopen(argv[2], "w");
    if (!fp)
    {
   
        printf("打开目的文件失败\n");
        exit(0);
    }

    fwrite(buffer, 1, fsize, fp);

4. mysys.c

4.1. 实验内容

实现函数mysys,用于执行一个系统命令,要求如下:

  • mysys的功能与系统函数system相同,要求用进程管理相关系统调用自己实现一遍
  • 使用fork/exec/wait系统调用实现mysys
  • 不能通过调用系统函数system实现mysys

4.2. 效果演示

测试程序

int main()
{
   
    printf("---------------------------------\n");
    mysys("echo a b c d");
    printf("---------------------------------\n");
    mysys("ls /");
    printf("---------------------------------\n");
    return 0;
}

输出结果

---------------------------------
a b c d
---------------------------------
bin  boot  dev  etc  home  init  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  snap  srv  sys  tmp  usr  var
---------------------------------

4.3. 实验思路和关键代码

通过在子进程中使用execl()函数调用sh命令实现简单的系统命令调用

    pid = fork();
    if (pid == 0)
        execl("/bin/sh", "sh", "-c", str, NULL);
    wait(NULL);

sh命令是shell命令语言解释器,执行命令从标准输入读取或从一个文件中读取。通过用户输入命令,和内核进行沟通


5. sh3.c

5.1. 实验内容

  • 该程序读取用户输入的命令,调用函数mysys执行用户的命令
    • 考虑如何实现内置命令cd、pwd、exit
  • 实现文件重定向
  • 实现管道
    • 只要求连接两个命令,不要求连接多个命令
    • 不要求同时处理管道和重定向

5.2. 效果演示

  • 打开后自动显示工作路径(pwd)
sh$ ./sh3

当前工作目录是: /计算机操作系统/实验/homework/sh
>
  • 读取指令并执行
当前工作目录是: /计算机操作系统/实验/homework/sh
> echo a b c
a b c

当前工作目录是: /计算机操作系统/实验/homework/sh
>
  • cd指令
当前工作目录是: /计算机操作系统/实验/homework/sh
> cd /

当前工作目录是: /
> ls
bin  boot  dev  etc  home  init  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  snap  srv  sys  tmp  usr  var
  • exit指令
当前工作目录是: /
> exit
已经退出shell
  • 重定向
当前工作目录是: /计算机操作系统/实验/homework/sh
> echo a b c >out.txt

out.txt文件内容

a b c

  • 管道
当前工作目录是: /计算机操作系统/实验/homework/sh
> cat /etc/passwd | wc -l
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
// 内容过多以下省略

5.3. 实验思路和关键代码

  • 实验的要求是从sh1到sh3逐渐增加的,其代码也是从简单到复杂逐步构建
字符串分割
  • 由于要处理输入的命令,所以我们要进行字符串的分割
    在实验过程中分析需求,决定构建以下数据结构,储存命令的缓冲区和需要进行分割得到的结构体
#define BUF_LEN 1024
char buffer[BUF_LEN];

#define ARGV_LEN 32
struct Command
{
   
    int argc;       //分割串的数量
    int redirectF;  //重定向标记
    int pipLineF;   //管道标记
    char *argv[ARGV_LEN];
};
struct Command command;
  • 对命令进行分割, 使用strtok函数

C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。

  • 对命令进行分割时,需要判断是否有’>‘重定向和’|‘管道命令。由于实验中并未同时支持重定向和管道命令,所以判断到’>‘或’|'时直接将它们对应的标记位置为其在char* argv[]中的位置
  • 分割部分代码
    //进行分割
    char *buf;
    buf = strtok(buffer, " ");
    while (buf != NULL)
    {
   
        if (buf[0] == '>')
        {
   
            command.argv[command.argc] = NULL;
            command.redirectF = command.argc;
            command.argc++;
            command.argv[command.argc] = (char *)malloc(sizeof(char) * (strlen(buf) +
  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值