操作系统简介
操作系统主要作用
- 给用户层提供一个统一的接口
- 管理硬件资源
操作系统硬件资源
主要有:处理器,内存,硬盘,I/O设备,总线
其中处理器有一些概念(其实就是处理器的特殊寄存器)需要了解一下:程序计数器(program counter),堆栈指针(stack pointer)以及程序状态字(PSW)
- 程序计数器就是对程序员可见的一组寄存器,其包含下一条指令要拉取的内存地址
- 堆栈指针是指向当前内存栈顶的指针
- 程序状态字包含一些条件代码位,可以被不同的指令设置。主要是CPU优先级,用户还是内核模式和其他的控制位
而且处理器有多核和单核处理器,所以引申出来就有多线程,多进程,超线程等等的概念,有了多线程后,就有了资源竞争,而后有了锁,调度,上下文切换等一系列的问题出现
内存主要有RAM(random access memory), ROM(read-only memory), EEPROM(electrially erasable PROM)和闪存(flash memory)。由于内存的大小有限制,所以有了虚拟内存,虚拟化,地址空间等概念,而且内存的内容是断电即失的,所以需要保存到硬盘上,也就有了文件系统。硬盘和内存之间的内容交换又有相应的页面置换算法的研究,其中有一个重要的概念MMU(memory management unit)
I/O设备主要是用来输入输出,因为需要及时反馈,所以又有了中断的方案来解决优先处理
总线是为了处理额外的扩展,常见的是PCIe总线接口,可以扩展网卡和硬盘等,usb也是总线的一种
还有一个重要的东西叫BIOS(basic input output system),这个是用来在计算机启动阶段进行自检的程序,主要是检查上述的硬件资源,从而进行统一管理
操作系统概念
其实有些概念上面已经提到了,这里只是更加细致介绍一些概念
进程
一个进程通常是一个正在运行的程序。
进程主要包含以下内容:
- 地址空间(address space),地址空间通常是一些列可读可写的内存地址,它包含了可执行程序,程序数据和堆栈信息
- 寄存器。程序计数器和堆栈指针
- 一堆文件描述符
- 告警信息
- 相关进程列表
- 其他需要的信息
进程切换的时候,需要保存进程运行的状态信息,大部分操作系统都是使用一个进程表(process table)来维护,挂起的进程通常由地址空间和进程表入口组成
进程可以创建子进程,如果两个进程之间需要同步信息,这称为进程间同步(interprocess communication)
进程在内存中分为代码段(text segement), 数据段(data segement)和堆栈段(stack segement)
后面会继续写进程和进程间通信相关知识
地址空间
地址空间的主要目的是保护和使用更大的内存空间
每个进程拥有自己的地址空间,地址空间有实际物理内存大小,在进程切换的时候,进程独占内存地址,从而让进程看起来能够使用更大的地址空间
文件
文件是将处理器和内存中容易丢失的内容,保存在硬盘中,所以文件可以理解成硬盘内容的抽象。系统调用需要提供创建文件,删除文件,读取文件和写入文件的操作
大部分系统都提供一个目录(directory),把多个文件集中在一起。主要模型如下
文件也有操作权限,所以也相对来说提供了保护
文件中的概念比较多,这里介绍基本的一些概念
- 文件描述符(file descriptor)。文件打开操作时,会返回一个文件描述符,后续操作可以通过这个文件描述符操作
- 挂载文件系统。外部存储,如U盘,需要被操作系统读写的时候,需要先挂载到文件系统后,才能进行操作
- 特殊文件(special file)。特殊文件主要是将I/O设备抽象成文件,然后进行读写。可以分为块特殊文件(处理磁盘)和字符特殊文件(处理打印机等)
- 管道(pipe)。管道其实是进程和文件两个相关的一个概念,管道是一种伪文件,可用于连接两个进程
保护
操作系统保护是一个很大的议题,有很多内容可以深挖。我们用户层面可以看到文件保护,在网络中,就有更多的保护议题,具体后面看情况介绍
Shell
shell
是大部分程序员都要接触到的东西,能够输入各种程序指令,从而完成想要的工作。这部分可以参考MIT 6.NULL。还是要建议看下shell
的操作
系统调用
系统调用(system call)是用户态的进程调用内核态的函数的方式。比如读取的系统调用过程
介绍一些系统调用的用法
进程相关
pid = fork()
。创建一个子进程,并返回pid
pid = waitpid(pid, &statloc, options)
。等待子进程挂起s = execve(name, argv, environp)
。替换进程的地址空间exit(status)
。中断进程执行并返回状态
文件操作
fd = open(file, how, ...)
。打开文件,并标记读写权限s = close(fd)
。关闭文件n = read(fd, buffer, nbytes)
。读取数据到缓冲区n = write(fd, buffer, nbytes)
。写缓冲区到文件positon = lseek(fd, offset, whence)
。移动光标s = stat(name, &buf)
。获取文件状态信息
文件目录管理
s = mkdir(name, mode)
。创建一个目录s = rmdir(name)
。 删除一个空目录s = link(name1, name2)
。创建一个新入口name2指向name1s = unlink(name)
。删除一个目录入口s = mount(special, name, flag)
。挂在一个文件系统s = umount(special)
。卸载一个文件系统
其他
s = chdir(dirname)
。 切换工作目录s = chmod(name, mode)
。修改文件保护位s = kill(pid, signal)
。 发送一个信号给进程seconds = time(&seconds)
。从Jan. 1, 1970开始获取过去的时间
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了