目录

job3/myecho.c

job3/mycat.c

知识点:

job3/mycp.c

job3/mysys.c

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

job3/sh1.c


job3/myecho.c

题目:

  • myecho.c的功能与系统echo程序相同

  • 接受命令行参数,并将参数打印出来,例子如下:

    $ ./myecho x
    x
    $ ./myecho a b c
    a b c

思路:

  • C程序的main函数原型,argc:命令行参数的个数,argv:命令行参数数组

    int main(int argc, char *argv[]);
  • 因此从第二行开始输出指令中的字符串就行

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

在一个终端中使用 gcc 编译器来编译程序并生成自定义目标文件

gcc -o myecho myecho.c

结果展示:


job3/mycat.c

题目:

  • mycp.c的功能与系统cp程序相同

  • 将源文件复制到目标文件,例子如下:

  • 要求使用系统调用open/read/write/close实现

    $ cat /etc/passwd
    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
    ...
    $ ./mycp /etc/passwd passwd.bak
    $ cat passwd.bak
    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

知识点:

文件操作:https://www.linuxmooc.com/courses/io/

用到的几个函数:

#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);//打开
int creat(const char *pathname, mode_t mode);//创建
int open(const char *pathname, int flags, mode_t mode);
int close(int fd);//关闭
#include <unistd.h>
int read(int fd, void *buf, size_t count);//读取
int write(int fd, void *buf, size_t count);//写入
off_t lseek(int fd, off_t offset, int whence);//定位

思路:

  • 打开文件,文件名就是输入指令的第二个字符串,进行健壮性检查。

  • 每次读取128字节数据并实时输出在屏幕上,STDOUT_FILENO是终端的描述符,直到文件末尾。也可以只读取1字节,更不容易溢出,就是效率可能没那么高。

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
void panic(char*message)
{perror(message);exit(EXIT_FAILURE);
}
int main(int argc,char *argv[])
{//open fileint fp=open(argv[128],O_RDONLY);if(fp<0)panic("open");//read filechar s[1];int flag;while((flag=read(fp,&s,1))>0){//write filewrite(STDOUT_FILENO,s,1);}close(fp);return 0;
}

在一个终端中使用 gcc 编译器来编译程序并生成自定义目标文件

gcc -o mycat mycat.c

结果:


job3/mycp.c

  • mycp.c的功能与系统cp程序相同

  • 将源文件复制到目标文件,例子如下:

  • 要求使用系统调用open/read/write/close实现

    $ cat /etc/passwd
    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
    ...
    $ ./mycp /etc/passwd passwd.bak
    $ cat passwd.bak
    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
    ...

思路和job2类似

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
void panic(char*message)
{perror(message);exit(EXIT_FAILURE);
}
int main(int argc,char *argv[])
{//open fileint fout=open(argv[1],O_RDONLY);if(fout<0)panic("open");//read filemode_t mode=0777;int fin=open(argv[2],O_RDWR|O_APPEND|O_CREAT,mode);char s[10];int flag;while((flag=read(fout,&s,1))>0){//write filewrite(fin,s,1);}close(fout);close(fin);return 0;
}

job3/mysys.c

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

  • mysys的功能与系统函数system相同,要求用进程管理相关系统调用自己实现一遍

  • 使用fork/exec/wait系统调用实现mysys

  • 不能通过调用系统函数system实现mysys

  • 测试程序

    #include <stdio.h>
    ​
    void mysys(char *command)
    {实现该函数,该函数执行一条命令,并等待该命令执行结束
    }
    ​
    int main()
    {printf("--------------------------------------------------\n");mysys("echo HELLO WORLD");printf("--------------------------------------------------\n");mysys("ls /");printf("--------------------------------------------------\n");return 0;
    }
  • 测试程序的输出结果

    --------------------------------------------------
    HELLO WORLD
    --------------------------------------------------
    bin    core  home        lib     mnt   root  snap  tmp  vmlinuz
    boot   dev   initrd.img      lost+found  opt   run   srv   usr  vmlinuz.old
    cdrom  etc   initrd.img.old  media   proc  sbin  sys   var
    --------------------------------------------------

在mysys函数中创建一个子进程,调用execl函数实现sh命令,并等待子进程结束。

execl函数:

int execl(const char *path, const char *arg, ...);

最后一个参数必须是NULL

第一个参数path指定被装入程序的路径。

这里需要使用的是sh指令,/bin/sh是指令路径,sh -c command是命令。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void mysys(char *command)
{pid_t pid;if(command==NULL){printf("Error: wrong command!");exit(0);}pid=fork();if(pid==0){error=execl("/bin/sh","sh","-c",command,NULL);if(error<0)perror("execl");}wait(NULL);
}
​
int main()
{printf("--------------------------------------------------\n");mysys("echo HELLO WORLD");printf("--------------------------------------------------\n");mysys("ls /");printf("--------------------------------------------------\n");return 0;
}

展示:


job3/sh1.c

  • 该程序读取用户输入的命令,调用函数mysys(上一个作业)执行用户的命令,示例如下

    # 编译sh1.c
    $ cc -o sh1 sh1.c
    ​
    # 执行sh1
    $ ./sh
    ​
    # sh1打印提示符>,同时读取用户输入的命令echo,并执行输出结果
    > echo a b c
    a b c
    ​
    # sh1打印提示符>,同时读取用户输入的命令cat,并执行输出结果
    > cat /etc/passwd
    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
  • 实现内置命令cd、pwd、exit

  • 首先在'>'后输入命令,当输入回车时触发功能函数。这里需要处理一下字符串,在回车处截断。

  • 添加exit,cd 的功能这里调用了exit(),chdir(),getcwd()函数。

    • chdir()同cd

      函数原型:int chdir(const char *path);

      功 能:更改当前工作目录。

      参 数:Path 目标目录,可以是绝对目录或相对目录。

      返回值:成功返回0 ,失败返回-1

    • getcwd()

      函数原型:char *getcwd( char *buffer, int maxlen );

      功 能:获取当前工作目录

      参数说明:getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小。

      返 回 值:成功则返回当前工作目录,失败返回 FALSE

    • exit()

      结束当前进程/当前程序

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/wait.h>
    #include<linux/string.h>
    #include<string.h>
    extern void mysys(char *command);
    ​
    int main()
    {while(1){char command[100]={0};char c;printf(">");//read from screenint i=0;do{c=getchar();command[i]=c;i++;}while(c!='\n');command[i-1]='\0';
    //exit功能if(!strcmp(command,"exit"))exit(0);
    //pwd功能else if(!strcmp(command,"pwd")){char *path=getcwd(NULL,0);printf("Current directory:%s\n",path);free(path);}
    //cd功能else if(command[0]=='c'&&command[1]=='d'){char cd[100]={0};strcpy(cd,command+3);int error=chdir(cd);if(error<0)perror("cd");else{char *path=getcwd(NULL,0);printf("Current directory:%s\n",path);free(path);}}
    //其他功能else mysys(command);}
    }
  • 要想调用mysys.c,首先得将其主函数注释掉。需要进行重定位,mysys作为外部符号需要用extern引用,并进行静态库链接。

将静态库中包含的目标模块先生成可重定位目标文件:
cc -c mysys.c
cc -c sh1.c
打包编译:
cc -o sh sh1.o mysys.o

展示:

操作系统实践 job3相关推荐

  1. 添加简单的linux内核模块,操作系统实践 第12章-添加最简单的Linux内核模块.ppt

    操作系统实践 第12章-添加最简单的Linux内核模块.ppt 文档编号:310662 文档页数:16 上传时间: 2018-07-21 文档级别: 文档类型:ppt 文档大小:2.00MB 第12章 ...

  2. 泛在操作系统实践案例

    本文字数:1399字 阅读时间:3 分钟 文章来源:<泛在操作系统实践与展望研究报告> 虽然泛在操作系统的概念是在 2018 年才正式由梅宏院士提出,但是与泛在操作系统相关的研究工作已经有 ...

  3. MIT6828操作系统实践记录(一)

    MIT6828操作系统实践记录(一) 最近经常感受到被大佬碾压,想想自己写了几年代码但对操作系统的理解似乎仍然停留在课本上-OTZ,特开此篇来进行实践.总结.感谢大佬们,大佬们的碾压就是我前进的动力. ...

  4. 操作系统实践 linux命令期末汇总

    操作系统实践 linux命令 Linux 1 简介 linux介绍 GPL linux发行版 linux系统标准化 登入与登出 常用快捷键 补充内容 Linux 2 Shell Shell 环境变量 ...

  5. Linux操作系统实践——Samba服务器搭建

    文章目录 Linux操作系统实践--Samba服务器搭建 一.实验目的 二.实验内容 ② 学生教师服务 三. 题目分析及基本设计过程分析 ② 学生教师服务 1) 整体思路 2) 系统用户和组分配设计说 ...

  6. 操作系统实践(四/五)

      本次实验课的内容涉及到以下几个方面:     1.文件的内核实现     2.标准的输入输出     3.系统调用dup和pipe   文件最基本的系统调用是open和close,open一个文件 ...

  7. 操作系统实践-BIOS

    基本概念:https://wiki.osdev.org/BIOS 所有中断列表:http://www.ctyme.com/intr/int.htm IBM PC 介绍:http://classicco ...

  8. 学习操作系统实践-Linux 操作系统从入门到提高(主编 王秀丽 于群 王震)

    前言 1.操作系统作为计算机软硬件的基础 2.Linux系统学习为明线,内容分层次递进,包括: (1)Linux系统基本使用(普通用户视角) (2)应用和系统编程(开发人员视角) (3)内核与应用(内 ...

  9. 【南航操作系统实践】job9

    文章目录 操作系统实验job9 实验内容 实验代码 `pc.c` `pp.c` 实验思路 操作系统实验job9 实验内容 使用信号量解决生产者.计算者.消费者问题 pc.c 使用信号量实现 ping- ...

  10. ROS机器人操作系统实践(一)—— 环境搭建

    虚拟机安装:后续ROS的大部分操作均在虚拟机中进行,选择VMware Workstation虚拟机平台. 可以在百度上搜索VMware Workstation的破解版安装,这里安装的是VMware W ...

最新文章

  1. R语言union函数计算数据对象(vector、list、dataframe)的并集:union函数计算两个vector向量、dataframe、列表list的并集
  2. [CES 2018] 与联想、小蚁合作,谷歌发布VR180系列VR相机
  3. 【开发环境】Ubuntu 中使用 VSCode 开发 C/C++ ③ ( 创建工程目录 | 添加 C++ 源代码 | 代码自动提示 )
  4. 树形结构:优先级队列,堆
  5. 处女座男生颜值测试软件,颜值在线又绅士的星座男(图)
  6. rsa 加密 js php,security.js+RSA做出加密功能
  7. 工作220:git clone的时候地址需要改成自己的用户名
  8. Java 反射(初步)
  9. 树——二叉树结点的删除与清除
  10. Project Euler Problem 27小结
  11. android 代码 华为 os,Android | 带你零代码实现安卓扫码功能
  12. 求计算机技术在创新上的应用,计算机技术在企业中的应用
  13. 打标工具labelme或者labelimg遇到图片闪退的完美解决方案
  14. 西威变频器avo下载调试资料_西门子变频器使用BOP-2 面板调试 G120
  15. 一文彻底搞懂 CTR 建模
  16. 【vue】webapp移动端模板
  17. 新浪微博平台架构(转)
  18. UOS/deepin上安装坚果云
  19. Install VirtualBox Guest Additions for elementary os
  20. 说话计算机,教计算机说话

热门文章

  1. redis的消息发布(publish)/ 订阅(subscribe)
  2. 001案例分析、常见项目管理名词
  3. 华为云内网DNS地址大全(不同区域DNS地址)
  4. webpack 拾翠:充分利用 CommonsChunkPlugin()
  5. 浅谈大数据时代之影响力
  6. 从敏思博客的倒闭事件看历史重现...
  7. 装两个独立的双系统,在笔记本电脑上
  8. 没人教的项目管理方法之(练好你的站桩) 一、 干系人分析应该怎么做
  9. 好看的原创弹窗公告代码分享
  10. centos离线安装(升级)nvidia显卡驱动及cuda10.2