加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

xv6 Shell & OS organization

发布时间:2020-12-15 09:08:10 所属栏目:安全 来源:网络整理
导读:Shell OS organization 主题: 内核系统调用API 参考:https://pdos.csail.mit.edu/6.828/2017/lec/l-shell.txt 对内核进行讲解并将homework shell进行说明 概述图 用户态如何连接内核态 应用程序 - printf() - write ) - SYSTEM CALL - sys_write() -

Shell & OS organization

主题:
内核系统调用API
参考:https://pdos.csail.mit.edu/6.828/2017/lec/l-shell.txt
对内核进行讲解并将homework shell进行说明

概述图

用户态如何连接内核态

应用程序 - > printf() - > write ) - > SYSTEM CALL  - > sys_write() - > ... 

用户级库是应用程序的私有业务

内核内部函数不能由用户调用

进程的状态,进程和线程区别是什么??

process=address space + thread(s)??

计算机系统进程由以下资源组成(或被称为拥有):

与程序关联的可执行机器码的图像。

内存(通常是虚拟内存的某个区域); 其中包括可执行代码,特定于
进程的数据(输入和输出),调用堆栈(用于跟踪活动子例程和/或其
他事件)以及用于保存在运行时产生的中间计算数据的堆。

分配给进程的资源的操作系统描述符,例如文件描述符(Unix术语)或句柄(Windows)以及数据源和接收器。

安全属性,例如进程所有者和进程的权限集(允许的操作)。

处理器状态(上下文),如寄存器内容和物理内存寻址。

进程和线程的一个简单解释

系统调用

xv6有几十个系统调用,而今天的Linux系统有几百个系统调用。

让我们回顾家庭作业2(sh.c)

为什么两个execv()参数?

execv 函数原型:execv(char cmd,char argv[]);
execv()用来执行参数path 字符串所代表的文件路径,与execl()不同的地方在于execve()只需两个参数,第二个参数利用数组指针来传递给执行文件.

/* 执行/bin/ls -al /etc/passwd */
#include <unistd.h>
main()
{
    char * argv[] = {"ls","-al","/etc/passwd",(char*)};
    execv("/bin/ls",argv);
}

返回值:如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中.

重定向

以下是可以用来重定向的命令的完整列表:

pgm > file  pgm 的输出被重定向到文件
pgm pgm 程序从文件度它的输入
pgm >> file pgm 的输出被添加到文件
n > file    带有描述符 n 的输出流重定向到文件
n >> file   带有描述符 n 的输出流添加到文件
n >& m  合并流 n 和 流 m 的输出

标准输入从开始行的下一个标记开始。
| 从一个程序或进程获取输入,并将其发送到另一个程序或进程。
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

管道

ls | wc -l 


如果ls产生的输出比wc消耗的更快呢?
如果ls比wc慢,该怎么办?
每个命令如何决定何时退出?
如果读者没有关闭写入结束呢?[尝试一下]
如果作者没有关闭阅读结束呢?
内核如何知道何时释放管道缓冲区?

shell如何知道管道何时完成?

例如:
ls | sort | tail -l
通过递归调用来解决先后完成的层次逻辑。
parsepipe(char **ps,char *es)
{
  struct cmd *cmd;
  cmd = parseexec(ps,es);
  if(peek(ps,es,"|")){
    gettoken(ps,0,0);
    cmd = pipecmd(cmd,parsepipe(ps,es));
  }
  return cmd;
}

UNIX系统调用观察

fork / exec拆分看起来很浪费 - fork()拷贝memory而exec()丢弃。

为什么不使用 pid = forkexec(path,argv,fd0,fd1) ?
fork / exec 分割是有用的:
fork(); I/O redirection; exec()
or fork(); complex nested command; exit.
如( cmd1 ; cmd2 ) | cmd3
fork() alone: parallel processing
exec() alone: /bin/login … exec(“/bin/sh”)
fork对于小程序来说很便宜 - 在我的机器上:
fork + exec需要400微秒(2500 /秒)
fork只需要80微秒12000 /秒)

文件描述符设计:

  • FDs是一个间接的等级

    • a process’s real I/O environment is hidden in the kernel
    • preserved over fork and exec
    • separates I/O setup from use
    • imagine writefile(filename,offset,buf size)

    • FDs help make programs more general purpose: don’t need special cases for files vs console vs pipe

Philosophy:小概念上简单的调用结合起来,

  • 系统调用函数,方便程序员使用

    例如fork(),open(),dup(),exec()
    command-line design has a similar approach
    ls | wc -l

为什么必须内核支持管道 - 为什么不用shell来模拟它们,

  • 例如:

    ls> tempfile; wc -l <??tempfile

猜测:如果用sh代替管道 执行的指令数,空间,时间都会变多。

系统调用接口简单,只是中断和字符缓冲区。为什么不用open()函数返回一个指向内核文件对象的指针?

ps:如果返回指针则能从用户层直接修改内核对象

核心的UNIX系统调用是古老的; 他们保持得好吗?

一方面来讲是非常成功的,历经多年的发展
  :设计迎合了命令行和命令行开发
    命令行用户,如命名文件,管道,
    对于开发,调试,服务器维护都很重要
但另一方面UNIX思路并不完美:
    系统调用API,程序员使用库通常不是很有价值,例如,隐藏sys调用细节的Python,
    或者在智能手机上 应用程序可能与文件&c一些UNIX抽象是不是非常有效
      而且fork()对于多GB进程是非常慢的
      FDs隐藏的细节可能是重要的,
        例如块大小的磁盘上的文件,
        例如时间和网络消息的大小,
所以有很多将来的计划工作:
  新的抽象的系统调用对于已有的系统调用

OS组织

如何实现一个系统调用接口?

为什么不是使用一个库?

即没有内核,只需在硬件上直接运行app +库即可。
灵活:应用程序可以绕过库,如果不正确的
应用程序可以直接与硬件交互
图书馆可以为一个单一目的的设备,
但如果计算机用于多个活动?

内核的关键要求:

隔离
多路复用
交互

helpful approach: abstract resources rather than raw hardware

File system,not raw disk
Processes,not raw CPU/memory
TCP,not ethernet packets
abstractions often ease isolation,multiplexing and interaction
also more convenient and portable

从隔离开始,因为这往往是最严格的要求。

隔离目标:

应用程序不能直接与硬件交互
应用程序不能损害操作系统
应用程序不能直接影响对方
应用程序只能通过操作系统界面与世界进行交互

处理器提供帮助隔离的机制

硬件提供用户模式和内核模式
有些功能只能在内核模式下执行
设备访问,处理器配置,隔离机制
*硬件禁止应用程序执行特权指令
- 而不是陷入内核模式
- 内核可以清理(例如,终止进程)
*硬件允许内核模式配置用户模式的各种约束
最关键的是:页表将用户的权限限制在自己的地址空间

内核构建在硬件隔离机制上

操作系统以内核模式运行
内核是一个大型的程序
服务:进程,文件,系统网络
低层设备,虚拟内存
所有的内核运行全硬件特权(方便)

应用程序运行在用户模式
- 内核设置每个进程隔离的地址空间
- 系统调用在用户和内核模式之间切换
应用程序执行一个特殊的指令进入内核,
硬件切换到内核模式
但只在内核指定的入口点

内核里要放什么?

  • xv6遵循传统的设计:操作系??统的所有内容都以内核模式运行

    • 一个带有文件系统,驱动程序和c的大型程序
    • 这种设计称为单核内核
    • 内核接口==系统调用接口
    • 优点:子系统可以很容易地配合
      一个由文件系统和虚拟内存共享的缓存

    • 缺点:交互复杂
      会导致内核中没有隔离错误

微内核设计

- 许多操作系统服务作为普通用户程序
  在文件服务器
- 内核实现在用户空间运行服务的最小机制 
  使用内存进程间通信(IPC)
- 内核接口!=系统调用接口      
-优点:多个隔离
-缺点:可能很难获得好的性能

外核:没有抽象

apps can use hardware semi-directly,but O/S isolates
应用程序可以读/写自己的页表,但是需要O / S审核
应用程序可以读/写磁盘块,但是O / S是块的所有者是
优点:对要求苛刻的应用程序有更多的灵活性
jos将是微内核和exokernel的混合

Next Lecture:x86硬件的隔离机制和xv6如何使用他们

参考:
重定向命令
shell&系统组织
进程和线程的一个简单解释
H-W shell

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读