百科问答小站 logo
百科问答小站 font logo



在没有GUI的时代(只有一个文本界面),人们是怎么运行多个程序的? 第1页

  

user avatar   brglng 网友的相关建议: 
      

TSR


user avatar   s.invalid 网友的相关建议: 
      

你把“文本界面”和“支持分时复用的多进程操作系统”混淆了。


先说文本界面。

不光Linux,windows的cmd、powershell等等,都是文本界面。

但文本界面并不等于“单进程”。


比如,Linux下,你完全可以在一个命令后跟一个&,把它置于后台:

wget zhihu.com/...../xxx.avi &


甚至于,你还可以定义一个shell 函数,这个函数通过&启动自己的两份拷贝……这就是著名的fork bomb:

:(){ :|: & };:


这是个故意写的让人不好懂的最简版本。写成这样就好懂多了:

fun() { fun | fun & }; fun


你可以在shell里面启动一堆进程,然后通过fg命令+作业编号把它调到前台。

事实上,Linux提供了一整套的作业控制命令,使得你可以同时启动很多程序,并指定任意一个在前台显示或将其置于后台:jobs、bg、fg 作业控制命令


如果你稍微学过点编程入门,那么应该知道标准输入stdin和标准输出stdout。

实质上,作业控制就是一个控制开关,可以随时指定哪个程序可以和当前终端通讯而已。


当然,你还可以通过ssh或telnet之类协议登陆远程计算机。这样一台Linux机器就完全可以同时支持你们全班几十人的编程作业了。

另外,事实上在Linux启动时,就为你一口气启动了7个终端;当你不小心把某个终端搞锁住、或者执行了太多任务不太好控制时,你可以按ctrl+alt+F1~F7组合键切换终端(视版本不同,F5/F7还可能是图形终端:当图形界面死掉时,你甚至可以切换到文本终端杀死图形管理器然后重启该终端的x服务)。所有终端里面跑的程序是相互独立的。


事实上,程序并不一定要让你看见。

比如很多服务程序就一直默默无闻的在后台干活,绝大多数人完全不知道它的存在——你可以打开windows的任务管理器,看看里面有多少你不知道是什么的进程。


Linux的服务程序(守护进程)必须明确放弃终端控制权:linux 守护进程编写 - zg_hover的专栏 - CSDN博客


总之,文本/命令行界面并不天然排斥多进程。


但是,DOS是一个单任务操作系统。

所谓单任务操作系统,是一种压根没有任务调度的“残疾”操作系统。


你可以认为,DOS是一个简单的程序;这个程序启动后,就“悬挂”在“等待终端输入”这个函数里;当你从键盘敲入字符后,它会解析你敲入的命令、然后让你指定的程序代替它的执行。


因为不存在任务调度,因此DOS无法支持多个进程同时执行。

想执行多个任务,就只能等前一个进程退出、然后再载入一个新的进程。


但有的时候,比如我们需要中文支持;同时又需要执行诸如TC之类程序;怎么办呢?


答案很简单:我们自己为DOS写一个简陋的多进程管理系统!


怎么写呢?

我们知道,用户敲键盘、时钟走过一段时间或者其他硬件发出中断信号,CPU都会自动跳转到相应的“中断服务程序”中,以尽快处理突发任务。


CPU是如何知道“中断服务程序”在哪呢?


很简单,它约定了一组“中断号”,比如3号中断就是单步执行,比如10H中断的13号子功能用来显示字符串,等等。


当中断发生时,根据中断号,CPU会从“中断向量表”首项+(中断号乘以4)个字节的位置读入4个字节的数据,这个数据就是中断服务程序所在的地址——或者叫函数指针。


因此,只要我们自己写一个中断服务程序,在内存中分配一块空间,把这个中断服务程序的机器码填入;然后把我们自己的中断服务程序的起始地址写到中断向量表的合适位置——那么,我们就动态替代了DOS提供的某些功能。


然后,哪怕我们的程序已经退出;但只要中断发生,CPU还是会乖乖执行我们刚刚安插进去的“奸细代码”。


这就叫TSR技术。


通过这种技术,我们就在DOS上实现了“多任务”——我们的程序藏在后台,为其他人写的程序提供服务。


当然,TSR的“多任务”是假的。如果两个程序都要TSR、而且又都看中了同一个中断……


因此,那时写程序是非常依赖“自觉”的。哪个中断已经被DOS占了、哪个中断又被UCDOS改写了,那么我们再写程序时,就最好不要再改写这个中断了——万一非改写不可,那么最好记住人家写入的中断服务程序地址,在执行完我们的程序后,别忘了调一下人家的中断服务程序。


但万一我们改完了人家以为自己驻留没成功再改一次……

显然,可怜的DOS系统就要被玩坏了。


不仅如此,可怜巴巴的一小段中断服务程序往往不足以容纳太过复杂的内容;但为了提供足够的功能,我们又需要载入大量的代码……

于是,就连动态载入/卸载程序代码也必须我们自己写。总之麻烦的很,又特别容易出错。


后来,微软自己搞了Windows 3.x;它终于有了一个真正的进程调度器,终于真正支持了多进程。

——这大概就是题主等很多人把文本界面默认为“单进程”、图形界面默认为多进程的原因吧。

——其实图形界面也完全可以是单进程的,比如图形化的bios设置界面。


Windows 3.x是非抢夺式多进程,一个程序执行一会儿,需要等磁盘等网络等键盘输入了,就主动放弃控制权,让别人也跑一会儿;但如果一个进程不自觉,就是霸着CPU不让开……


到了Windows 95,这才有了依时间片分配执行时间的抢夺式多进程。到这时,它才终于称得上一个现代化的、真正支持多任务的操作系统。




  

相关话题

  一个模块(比如文件系统)在内核中实现(宏内核),跟它在内核外实现(微内核),主要区别是什么? 
  为什么有些usb数据线时间长了就不能再传输数据了? 
  哪种操作系统可以兼容另一个操作系统的应用,但又不"基于"它? 
  我听说以前的系统没有图形界面,那他们是用 C# 等语言直接敲代码吗? 
  野指针危害真的很大吗? 
  假如当年微软继续开发DOS,今天的DOS会是怎样? 
  用Android系统做出的游戏主机为何与XBOX、PS的游戏体验相去甚远? 
  鸿蒙系统到底是不是安卓系统? 
  华为 9 月 25 日全新发布的 openEuler 欧拉操作系统是不是套壳CentOS 操作系统? 
  程序中的堆和栈大小是动态变化的,还是相对固定的? 

前一个讨论
年轻人追求的「独立」究竟是什么?
下一个讨论
铁三角的ATH-M50X值得购买吗?





© 2024-11-16 - tinynew.org. All Rights Reserved.
© 2024-11-16 - tinynew.org. 保留所有权利