搜索
bottom↓
回复: 50

版主,想听下高手们对进程和线程的理解!

[复制链接]

出0入0汤圆

发表于 2010-8-24 13:17:43 | 显示全部楼层 |阅读模式
版主,想听下高手们对进程和线程的理解!
一直以来做的都是单片机相关的东西,用的os也都是在无mmu的mcu上,如ucos等,但却发现越来越对进程感到模糊了!在这里想听下大侠们对进程如何看待?

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入618汤圆

发表于 2010-8-24 13:41:14 | 显示全部楼层
最基本的区别就是进程之间地址空间是独立的,而线程之间是共享的。
不具备MMU的MCU理论上跑的都是线程。

出0入0汤圆

发表于 2010-8-24 15:25:00 | 显示全部楼层
一车间、二车间以及各个车间内部流水线的差异。

出0入0汤圆

 楼主| 发表于 2010-8-24 15:28:48 | 显示全部楼层
gzhuli 咕唧霖
好像是先有进程的概念再有的线程,对于早期的cpu都是没有MMU的但那时进程概念已经出现了啊!

出0入0汤圆

 楼主| 发表于 2010-8-24 15:34:19 | 显示全部楼层
【2楼】 dhyana
是不是可以说一个main就是一个进程,至于main里做什么,怎么做, 是多线程还是死循环无所谓。
也就是说一个可以独立运行的代码段可是认为是一个进程,就像你说的一个车间可以独立工作一样!

出0入0汤圆

 楼主| 发表于 2010-8-24 15:39:11 | 显示全部楼层
【1楼】 gzhuli 咕唧霖:
不具备MMU的MCU理论上跑的都是线程!如何理解?
uclinux运行的可不可以称为进程?
如果我在编译时人为的分给每段程序(可以独立运行)一个真实的物理空间呢?
这样做是不是也可以在NO MMU的MCU上实现所谓的进程!

出0入0汤圆

发表于 2010-8-24 16:03:21 | 显示全部楼层
如【1楼】 gzhuli 咕唧霖所述,进程和线程的核心在于“地址空间”的封闭性/独立性;不在于跑的是什么代码。

无MMU的系统上,一段程序所占据的地址空间是不封闭的,别人可用指针访问。
无MMU,有MPU系统上,地址空间可以是封闭的,但不是全空间独享。不是严格的。

出0入0汤圆

发表于 2010-8-24 16:27:15 | 显示全部楼层
原来是DJY。。。不懂

出0入0汤圆

 楼主| 发表于 2010-8-24 17:13:22 | 显示全部楼层
【6楼】 dr2001:

能从程序员的角度
或是操作系统实现角度
或是进程调度实现的角度
或是线程调度实现的角度

说明一下吗?

出0入0汤圆

 楼主| 发表于 2010-8-24 17:14:12 | 显示全部楼层
也好给我们这些新手们一些启发!

出0入0汤圆

 楼主| 发表于 2010-8-24 17:18:02 | 显示全部楼层
再问下能否在NO MMU的情况下实现所谓的进程调度?

当然你可以假设只有两个进程,
假设每个进程可以拥有自己个唯一的不重叠的地址空间
等等等。。。。。。。。。。。。

只要可以实现所谓的进程调度?就可以算!

出0入0汤圆

发表于 2010-8-24 17:39:17 | 显示全部楼层
想想linux上面把同一个多任务的程序用fork来实现和用pthread来实现的区别能明白点吧
一开始写linux程序的时候就干过这样的事情...

进程线程应该都是操作系统相关的概念吧,不同的操作系统就不一样
以前玩过TI DSP的DSP BIOS(也算操作系统吧?)似乎就只有“任务”的概念?(不确定,没深入玩)
如果对于一个多任务的程序,自己写汇编程序,可能共用内存的几个区块,也可能分开,那么应该就没有进程和线程的概念了?

出0入618汤圆

发表于 2010-8-24 17:45:53 | 显示全部楼层
调度是一回事,内存管理是另一回事,在OS中是两个分开的模块。
对于调度器,线程是最小调度单位。
对于内存管理器,进程是最小管理单位。

没有MMU能否实现调度?当然可以。
没有MPU/MMU能否实现内存隔离?不可以。
单纯对于调度器来说进程和线程没什么区别,但对于整个OS来说,进程和线程的最大区别就是内存管理。
ucLinux可以在API层面模拟进程行为,但无法在硬件级别做到进程隔离,所以系统健壮性比起Linux是有很大缺失的。

出0入0汤圆

 楼主| 发表于 2010-8-24 18:48:43 | 显示全部楼层
【12楼】 gzhuli 咕唧霖

对你说的好像有点明白了!有点晕了

能能简述下进程调度的过程?
比如下面线程调度的简单过程:
                                                        
main()--->系统初始化---->运行第1个死循环的函数---->系统ticks到了进入中断---->保存当前上下文到该中断了作务堆栈---->
找到下一个死循环的函数----->取出其堆栈指内容恢复上下文----->继续运行----->系统ticks到了进入中断..................

出0入0汤圆

发表于 2010-8-24 20:06:43 | 显示全部楼层
进程是神族的航母,线程是小飞机

出0入0汤圆

发表于 2010-8-24 22:30:19 | 显示全部楼层
我试着解释一下,首先打个比喻。
最初,福特老先生修了一个车间来造汽车,并修了一个发电厂为车间提供动力。
开始,只有一条生产线,日夜运转,该生产线就是整个车间的全部。咦,这不就是单进程嘛,对了,所有裸奔系统,都可以看成是一个单进程系统。

后来,福特汽车销量看好,一条生产线不够了,福特先生看到车间还有空间(内存足够),发电厂负荷也不足(CPU速度够快),就增加了若干条生产线。嗯,这就是多进程,进程就是可以完成独立的计算任务的机构。

多条生产线建立后,产能又过剩了,于是福特就把生产线租给了老朋友丰田先生,丰田则把生产线按照自己的模式加以改造,生产丰田汽车。对了,进程是独立的,可以完成任何想做的工作,既可以生产福特,又可以生产丰田。

问题产生了,丰田由于经营得好,销量大增,大大积压了福特的市场,福特的工人不干了,老到丰田这边捣乱,于是福特和丰田这对老朋友商量着,在各自的生产线之间建立起隔离墙。看见了吧,MMU来了,进程和MMU之间是父子关系,不是鸡蛋关系。现代多进程的计算机系统中,由于MMU成了标配,所以容易混淆MMU和进程之间的关系。

一条生产线由许多环节组成,这些环节构成流水线上的许多结点,各自独立地完成工作,但共享流水线上的许多资源,数据(半成品)也要互相传送,这就是线程,因此,线程的概念必然先于进程产生的。

单进程系统中,只有一个main函数,多进程系统中,表面看来是有多台_独立的计算机,自然有多个main函数。
调度器本身不会去创建进程和线程,而是提供一系列接口让程序员能够创建线程和进程,操作系统加载程序初始化调度器后,会继续创建系统中的第一个进程,然后启动之,这就是系统的第一个main函数,然后再干什么,就看你的了,你可以创建许多进程,也可以独占CPU,随你了。

调度器的目标,就是决定CPU执行哪个进程,选中进程后,就从上次挂起的地方开始运行。

出0入0汤圆

发表于 2010-8-25 00:16:23 | 显示全部楼层
DJY解释的不错~~~~

出0入0汤圆

 楼主| 发表于 2010-8-25 09:03:08 | 显示全部楼层
非常感谢楼上的所有兄弟们,
看来要想理解进程光靠解释是没用的,必须得深入代码这样才能真正明白什么是进程?怎样实现多进程?
此贴作为标记,等俺理解了多进程后,再回来叙述...

出0入0汤圆

发表于 2010-8-25 09:47:27 | 显示全部楼层
在 ARM 上实现的 多进程 操作系统:

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4125162&bbs_page_no=1&search_mode=3&search_text=liuweiele&bbs_id=9999

出0入0汤圆

 楼主| 发表于 2010-8-25 10:44:03 | 显示全部楼层
ls能给些代码看看吗?关于进程的?

出0入0汤圆

 楼主| 发表于 2010-8-25 12:06:22 | 显示全部楼层
【15楼】 djyos 都江堰操作系统:
因此,线程的概念必然先于进程产生的。

好像是先有进程的概念,再有的线程的概念!

操作系统为了使程序并发执行而产生了进程。

线程引入的原因: 为了减少程序并发执行所付出的时空开销,使os具有更好的并发性。

出0入0汤圆

 楼主| 发表于 2010-8-25 12:09:27 | 显示全部楼层
转载:http://www.cnblogs.com/mapk/archive/2008/01/26/1041919.html


复习功课:对进程、线程、应用程序域的理解

    前几天面试的一道题是谈谈进程、线程、应用程序域的区别,虽然能说上来几点,但感觉理解的很肤浅、很不透彻,闲暇时从书箱里翻出尘封已久的《操作系统》(还好,毕业时偶没舍得卖),翻了翻进程的那一章。看之前我列出了下面三个问题:
1. 这些概念(技术)出现的背景以及要解决的问题 (要干什么)
2. 它们之间的联系与区别
3. 三者之间的发展脉络

进程的出现:
(复习功课嘛,就把相关的内容都看看了,哎,都忘的差不多了)
  进程由操作系统创建、管理的,离开了操作系统也就不谈什么进程了,先看看操作系统的四个基本特征:
  1.并发(concurrence)
      并行性与并发性这两个概念是既相似又区别的两个概念。并行性是指两个或者多个事件在同一时刻发生,这是一个具有微观意义的概念,即在物理上这些事件是同时发生的;而并发性是指两个或者多个事件在同一时间的间隔内发生,它是一个较为宏观的概念。在多道程序环境下,并发性是指在一段时间内有多道程序在同时运行,但在单处理机的系统中,每一时刻仅能执行一道程序,故微观上这些程序是在交替执行的。  应当指出,通常的程序是静态实体,它们是不能并发执行的。为了使程序能并发执行,系统必须分别为每个程序建立进程。进程,又称任务,简单来说,是指在系统中能独立运行并作为资源分配的基本单位,它是一个活动的实体。多个进程之间可以并发执行和交换信息。一个进程在运行时需要运行时需要一定的资源,如 cpu,存储空间,及i/o设备等。在操作系统中引入进程的目的是使程序能并发执行。
  2.共享 (sharing)
    所谓共享是指,系统中的资源可供内存中多个并发执行的进程共同使用。由于资源的属性不同,故多个进程对资源的共享方式也不同,可以分为:互斥共享方式 和 同时访问方式
  3.虚拟 (virtual)
    是指通过技术吧一个物理实体变成若干个逻辑上的对应物。在操作系统中虚拟的实现主要是通过分时的使用方法。显然,如果n是某一个物理设备所对应的虚拟逻辑设备数,则虚拟设备的速度必然是物理设备速度的1/n。
  4.异步 (asynchronism)
    在多道程序设计环境下,允许多个进程并发执行,由于资源等因素的限制,通常,进程的执行并非“一气呵成”,而是以“走走停停”的方式运行。内存中每个进程在何时执行,何时暂停,以怎样的方式向前推进,每道程序总共需要多少时间才能完成,都是不可预知的。或者说,进程是以一步的方式运行的。尽管如此,但只要运行环境相同,作业经过多次运行,都会获得完全相同的结果,因此,异步运行方式是运行的。

可见,操作系统为了使程序并发执行而产生了进程。

进程的定义:可并发执行的程序在一个数据集合上的运行过程。
进程的特征:
1.动态性 进程既然是进程实体的执行过程,因此进程是有一定的生命期。而程序只是一组有序指令的集合,并放在某种介质上,本身无运行的含义,因此程序是个静态的实体。
2.并发性
3.独立性  这是指进程实体是一个能独立运行的基本单位,同时也是系统种独立获得资源和调度的基本单位。
4.异步性
5.结构特征 从结构上看,进程实体是由程序段、数据段及进程控制块三部分组成。
   (进程控制块(PCB):进程控制块是进程实体的一部分,它记录了操作系统所需要的、用于描述进程情况及控制进程运行所需的全部信息。os 是根据PCB来对并发执行的进程进行控制和管理的)

关于进程的总结:
定义:可并发执行的程序在一个数据集合上的运行过程,每个进程有一个自己的地址空间以及一个单一的控制流程。
要解决的问题:为了使程序能并发执行,(要并发执行就要隔离进程,使进程独立,即每个进程有属于自己的数据段、程序段、进程控制块)

线程的出现:

    我们首先回顾进程的两个基本属性:(1)进程使一个可拥有资源的独立单位 (2)进程同时又是一个可以独立调度和分派的基本单位。正是由于这两个基本属性,才使进程成为一个能独立运行的基本单位,从而构成了进程并发执行的基础。
   为了使程序能并发执行,系统必须进行以下操作:
(1) 创建进程。创建一个进程时必须为之人、分配所必需的、除处理器以外的所有资源,如内存空间、I/O设备以及建立相应的PCB.
(2) 撤消进程。系统在撤消进程时,需要先对这这些资源进行回收,然后再撤销PCB.
(3) 进程切换。在对进程进行切换时,由于要保留当前进程的CPU环境和设置新选中的进程的CPU环境,为此须花费不少处理器时间。
   简言之,由于进程是一个资源的拥有者,因而在进程的创建、撤销、和切换的过程中,系统必须为之付出较大的时空开销,也正因为如此,在系统中设置的进程的数目不宜过多,进程的切换的频率也不宜过高,但这也就限制了并发程度的进一步提高。为了解决这个问题,不少操作系统的学者们想到:将进程的两个属性分开,由操作系统分开处理。即对作为调度和分派的基本单位,不同时作为独立分配资源的单位,以使之轻装运行;而对拥有资源的基本单位,又不频繁地对之进行切换,在这种思想的指导下,产生了线程的概念。

线程引入的原因: 为了减少程序并发执行所付出的时空开销,使os具有更好的并发性。

    在引入线程的os 中,线程是进程中的一个实体(进程中的一个或多个指令执行流),是被系统_独立调度和分派的基本单位。线程基本上不再拥有系统资源,(只拥有一点在运行中必不可少的资源,如程序计数器、寄存器和栈),但它可与同属一个进程的其他线程功能共享进程所拥有的全部资源。线一个线程可以创建和撤销另一个线程;同一进程中的多个线程之间可以并发执行。

线程与进程的比较:
    线程具有许多传统进程所具有的特征,故又称为轻型线程或进程元;而把传统的进程称为重型进程。在引入了线程的os中,通常一个进程拥有若干个线程。下面从四个方面来比较线程与进程。
1.调度
   在“原始”的OS中,拥有资源的基本单位和独立调度、分配的基本单位都是进程。而在引入线程的OS中,则把线程作为调度和分派的基本单位,而把进程作为资源拥有的基本单位,使传统进程的两个属性分开,线程便能轻装运行,从而可以显著的提高系统并发程度。在同一进程中,线程的切换不会引起进程切换,在由一个进程中的线程切换到另一进程中的线程时,将会引起进程切换。
2.并发性
    在引入线程的OS中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间亦可以并发执行,因而使OS具有更好的并发性,从而能更有效的使用系统资源和提高系统吞吐量。
3.拥有资源
    不论是“原始”的OS,还是设有线程的操作系统,进程都是拥有资源的一个独立单位,它可以拥有自己的资源。线程自己基本不再拥有系统资源,但它可以访问其隶属进程的资源。
4.系统开销
    由于在创建或撤销进程时,系统都要为之分配或回收资源,如内存空间,I/O设备等。因为,OS所付出的开销将显著地大于在创建或撤销线程时的开销。类似的,在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU 环境设置。而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销。此外,由于同一进程中的多个线程具有相同的地址空间,使它们之间的同步和通信的实现变得比较容易。
    这个机制在现代操作系统的实现主要可分为两大类。即根据操作系统内核是否对线程可感知,分为内核线程和用户线程。
1.内核线程   无论是用户进程中的线程还是系统进程中的线程,它们的创建、撤销和切换都是由内核实现的。在内核中保留了一张线程控制块,内核根据该控制块而感知线程的存在并对线程进行控制。
2.用户线程      它仅存在于用户级中,对于这种线程的创建、撤销和切换,都不利用系统调用实现,因而这种线程与内核无关。相应地,内核也并不知道用户级线程的存在。( 调度的实现方式是采用在用户空间增加运行库,这些运行库被称为“线程包”,每当用户进程获得CPU控制权,线程运行库决定该从哪里开始运行)

( 实际上,上面所说的线程是操作系统调度的基本单位,实际上指的只是内核线程。操作系统在调度时,参考各进程内的线程运行情况做出调度决定,如果一个进程中没有就绪态的线程,那么这个进程也不会被调度占用CPU.
  在Windows 2000中,操作系统进行调度时根本就不理采线程是属于哪个进程的,只是将所有的就绪线程统一排成若干个优先级队列,然后进行调度。在这个情况下,线程的确成了调度的最小单位)。

关于线程的总结:
出现的背景:由于进程是一个资源的拥有者,因而在进程的创建、撤销、和切换的过程中,系统必须为之付出较大的时空开销,限制了并发程度的进一步提高。
要解决的问题:解决进程的创建、撤销、和切换的过程中,系统必须为之付出较大的时空开销的问题
解决的方法:将进程的两个属性分开,由操作系统分开处理。把“独立调度、分配的基本单位”这个属性分离出来作为线程;而把进程作为资源拥有的基本单位,线程作为进程中的一个实体而存在。

应用程序域的出现:
(来自msdn)
   在.net出现以前,一个进程下,只能运行一个应用程序,而在,net出现后,一个进程下,可以运行多个应用程序,这都是因为应用程序域的出现。
    以前使用进程边界来隔离在同一台计算机上运行的应用程序。每一个应用程序被加载到单独的进程中,这样就将该应用程序与在同一台计算机上运行的其他应用程序相隔离。
   隔离这些应用程序的原因在于内存地址是与进程相关的;在目标进程中,不能通过任何有意义的方式使用从一个进程传递到另一个进程的内存指针。此外,您不能在两个进程间进行直接调用。您必须代之以使用代理,它提供一定程度的间接性。
    应用程序域提供安全而通用的处理单元,公共语言运行库可使用它来提供应用程序之间的隔离。您可以在具有同等隔离级别(存在于单独的进程中)的单个进程中运行几个应用程序域,而不会造成进程间调用或进程间切换等方面的额外开销。在一个进程内运行多个应用程序的能力显著增强了服务器的可伸缩性。
     隔离应用程序对于应用程序安全也是十分重要的。例如,您可以在单个浏览器进程中运行几个 Web 应用程序中的控件,同时使这些控件不能访问彼此的数据和资源。

应用程序域所提供的隔离具有以下优点(引入原因):
    在一个应用程序中出现的错误不会影响其他应用程序。因为类型安全的代码不会导致内存错误,所以使用应用程序域可以确保在一个域中运行的代码不会影响进程中的其他应用程序。
    能够在不停止整个进程的情况下停止单个应用程序。使用应用程序域使您可以卸载在单个应用程序中运行的代码。
    应用程序域形成了托管代码的隔离、卸载和安全边界。线程是公共语言运行库用来执行代码的操作系统构造。在运行时,所有托管代码均加载到一个应用程序域中,由特定的操作系统线程来运行。
    应用程序域和线程之间不具有一对一的相关性。在任意给定时间,在单个应用程序域中可以执行几个线程,而且特定线程并不局限在单个应用程序域内。也就是说,线程可以自由跨越应用程序域边界;不为每个应用程序域创建新线程。
    在任意给定时间,每一线程都在一个应用程序域中执行。运行库会跟踪在哪些应用程序域中有哪些线程正在运行。

出0入0汤圆

发表于 2010-8-25 12:33:02 | 显示全部楼层
回复【20楼】clingos
【15楼】 djyos 都江堰操作系统:
因此,线程的概念必然先于进程产生的。  
好像是先有进程的概念,再有的线程的概念!
操作系统为了使程序并发执行而产生了进程。
线程引入的原因: 为了减少程序并发执行所付出的时空开销,使os具有更好的并发性。

-----------------------------------------------------------------------

进程先被抽象出来,不等于进程的概念先产生。
线程是一条流水线内的多道并发工艺,进程是要在CPU内创建多条并发流水线才产生的,你说哪个会先产生?
线程的概念产生后,并没有名份,直到进程产生后,为了区别,才被命名为线程的。
头像被屏蔽

出0入0汤圆

发表于 2010-8-25 12:40:36 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2010-8-25 12:48:47 | 显示全部楼层
很好的讨论,认真学习!这就是我爱OurDEV的原因!

出0入0汤圆

发表于 2010-8-25 12:59:47 | 显示全部楼层
回复【21楼】clingos
-----------------------------------------------------------------------

这里提到的.net的应用程序域,是我心中永远的痛,这是djyos MP版本上打算使用的技术,被MS抢了先……

出0入618汤圆

发表于 2010-8-25 14:47:28 | 显示全部楼层
进程是早于线程出现的。

在50年代末期,由于电脑性能的提升,执行一段程序的时间越来越短,这就造成了花在输入输出上的时间比例越来越高(当时还在用打孔纸带输入程序和数据,用打印机输出结果),也就是说电脑快了,但运算效率并没有提高多少。于是人们就发明了批处理系统,一次将多个程序输入电脑,自动连续执行后又一次性输出结果。
到了60年代,批处理系统也不能满足电脑的胃口了,所以就开始出现多任务操作系统,当电脑等待输入输出时,可以切换到另一个程序运行,这就是进程的雏形。由于这个年代还没有进程隔离的概念,按今天的角度看实际上进程和线程是个同义词(但我不认为可以把当时的进程等同于今天的线程)。
到了70年代,电脑已经进入大型主机时代,可以由多人共享同一台电脑的计算资源,同时也产生了进程隔离等需求。此时Unix开始确立其主流地位。
到了70年代末期,随着电脑计算能力的提升,并发运行的进程越来越多,进程的创建、删除开销和进程间通讯成为性能瓶颈,人们又开始怀念没有进程隔离的并发执行能力,于是才产生了轻量级进程(即今天的线程)概念。

从OS发展历史可见,是先有“多生产线”的概念,再有“生产线流水作业”概念的。

出0入0汤圆

 楼主| 发表于 2010-8-25 15:10:53 | 显示全部楼层
【26楼】 gzhuli 咕唧霖

认同!

即多进程是满足多个应用程序并行“执行”提出的,而应用程序是如何实现的可以是多线程方式也可以是死循环方式。

从实现方式来看多进程难于多线程的实现!

出0入0汤圆

发表于 2010-8-25 23:54:29 | 显示全部楼层
to【12楼】 gzhuli 咕唧霖
---------------------------------------------
进程和线程最主要的区别就是能否共享地址空间,进程之间不能共享,同一个进程内的不同线程可以共享。

这种说法是现在对进程和线程的解释:没有MMU,内存就无法隔离,这是从硬件或者操作系统的角度来说的;

然而,历史上,一开始的计算机是没有MMU的,这时候已经有进程了,怎么理解?

从应用程序的角度来说,即使地址空间是共享的,没有办法定位到需要的变量,也是白搭,相当于没共享(破坏性的行为除外),这时候就是进程;自己写的程序,运行起来就是一个进程,里面包含多个线程,这时候,多个线程可以访问进程框架内的同一个变量,这就叫线程。

虽然从不同角度有不同的理解,本质区别还是在于对内存的共享。

ps.
可以使用多线程,不等于说操作系统本身就支持多线程。windows/Linux是以线程为单位调度的;而Unix以进程为单位调度的(以前是,好久没关注,新的不清楚),系统根本不知道有线程这回事儿。因此,windows/Linux里面,n个线程,会分配n个时间片;而Unix里面,n个线程,也只能分配1个时间片。

出0入0汤圆

发表于 2010-8-26 08:12:28 | 显示全部楼层
进程  是一大坨线程

出0入0汤圆

发表于 2010-8-26 10:42:31 | 显示全部楼层
回复【19楼】clingos
ls能给些代码看看吗?关于进程的?

-----------------------------------------------------------------------

我设计的多进程OS部分代码:

void*        LoadProcess(char *path) => 丛disk加载进程文件到物理内存,path为文件路径
{
        HANDLE hfile;
        U32 fsize;
        U32 *buf;
        ////
       
        hfile        =OpenFile(path,"rw");
        if(hfile==0)        return 0;
        fsize        =GetFileSize(hfile);
        if(fsize==0)        return 0;
       
        buf        =ProcessAlloc(fsize);
        if(buf==0)        return 0;
       
        fsize        =ReadFile(hfile,buf,fsize);
        CloseFile(hfile);
       
        if(fsize==0)
        {
                ProcessFree(buf);
                return 0;
        }
       
        if(buf[1]!=0x01234567||buf[2]!=0x76543210)
        {
                DebugPrintf("Process File Err!\n");
                ProcessFree(buf);
                return 0;
        }
       
        buf[4]        =GetAPIEntry();
        //((U32*)proc)[4]
       
        DebugPrintf("\n");
        DebugPrintf("********  Process Info  ********\n");
        DebugPrintf("Path: %s\n",path);
        DebugPrintf("Size: %dByte\n",fsize);
        DebugPrintf("PID:  %08XH\n",buf);
        DebugPrintf("RO:   %08XH - %08XH\n"                ,buf[8],buf[9]);
        DebugPrintf("RW:   %08XH - %08XH\n"                ,buf[10],buf[11]);
        DebugPrintf("ZI:   %08XH - %08XH\n"                ,buf[12],buf[13]);
        DebugPrintf("HeapSize:  %dByte\n"                ,ProcHeapSize(buf));
        DebugPrintf("StackSize: %dByte\n"                ,ProcStackSize(buf));
        DebugPrintf("ProcSize:  %dByte\n"                ,ProcSize(buf));
        DebugPrintf("Priority:  %d\n"                        ,ProcPriority(buf));
        DebugPrintf("Name:      %s\n"                        ,(U8*)buf+buf[17]);
        DebugPrintf("Icon:      %08XH\n"                ,buf[18]);
        DebugPrintf("Version:   %s\n"                        ,(U8*)buf+buf[20]);
        DebugPrintf("Date:      %s\n"                        ,(U8*)buf+buf[21]);
        DebugPrintf("Time:      %s\n"                        ,(U8*)buf+buf[22]);
        DebugPrintf("Desc:      %s\n"                        ,(U8*)buf+buf[23]);

        DebugPrintf("********************************\n");

        return buf;
       

}

HANDLE  CreateProcess (char *path, void *p_arg,char *cur_dir ) =>创建进程
{
    STK    *stk_cur,*stk_base;
    TCB    *ptcb;
    void         *proc;
   

       
    EnterCritical();
    if (CriticalNesting > 0)
    {    //不能在中断中创建进程.
        ExitCritical();
        return 0;
    }
    ExitCritical();

       
        ptcb        =(TCB*)MemAlloc(sizeof(TCB));
        if(ptcb==(TCB*)0)         
        {
            return 0;
        }
       
        ptcb->OSTCBType        =TCB_TYPE_PROCESS;
       
        ////加载进程
        proc        =(void*)LoadProcess(path);       
        if(proc==0)
        {
                MemFree(ptcb);
                return 0;
        }
       
        ////登记进程绝对路径
        ptcb->Path        =(char*)MemAlloc(StrLen(path));
        StrCopy(ptcb->Path,path);
       
        ////登记进程当前路径
        if(cur_dir)
        {
                StrCopy(ptcb->CurrentDir,cur_dir);
        }
        else
        {
                int i;
                i=StrLen(path);
                while(i)
                {
                        if(path=='\\')
                        {
                                path='\0';
                                StrCopy(ptcb->CurrentDir,path);
                                break;
                        }
                       
                        i--;
                }
               
        }
               
        stk_base        =(STK*)ProcStackStart(proc);
        if(stk_base==(STK*)0)
        {       
                MemFree(ptcb->Path);
                MemFree(ptcb);
                return 0;
        }

    stk_cur = StkInit((void(*)(void*))ProcROBase(proc), p_arg, stk_base, 0);   
         
    err = TCBInit(ptcb,ProcROBase(proc),ProcPriority(proc), stk_cur, stk_base, ProcStackSize(proc),OS_STAT_RDY,proc,ProcSize(proc));
    if (err != OS_NO_ERR)
    {
            MemFree(ptcb->Path);
                MemFree(ptcb);
                return 0;
    }
   
    if (OSRunning == TRUE)
    {   
OS_ThreadSched();
    }
     
    return (HANDLE)ptcb;

}

void        MMU_Sched(void) => 页面切换
{
    if(ReadyTCB->PAStart)
    {
             if(ReadyTCB->PAStart!=CurrentTCB->PAStart)
              {
          MMU_Remap(ReadyTCB->VAStart,ReadyTCB->PAStart,ReadyTCB->MemSize);
              }
    }

}

示例:

(原文件名:未命名.JPG)

出0入0汤圆

 楼主| 发表于 2010-8-27 14:32:19 | 显示全部楼层
void* LoadProcess();
加载的是什么格式的文件bin吗?
还是elf的?

出0入0汤圆

发表于 2010-8-27 17:07:41 | 显示全部楼层
回复【31楼】clingos
void* loadprocess();
加载的是什么格式的文件bin吗?
还是elf的?

-----------------------------------------------------------------------

bin

出0入0汤圆

发表于 2010-8-27 17:13:09 | 显示全部楼层
回复【31楼】clingos
void* loadprocess();
加载的是什么格式的文件bin吗?
还是elf的?

-----------------------------------------------------------------------

我自定义的可执行文件格式,不受编译器的限制,用ads,gcc都能直接编译出可执行的应用程序.

出0入0汤圆

发表于 2010-8-27 17:51:15 | 显示全部楼层
呵呵

出0入0汤圆

发表于 2010-9-6 14:29:54 | 显示全部楼层
顶,ourDEV的讨论就是热烈和谐...

出0入0汤圆

发表于 2010-9-6 14:49:13 | 显示全部楼层
看了高手们对进程线程的犀利分析和解释,收益匪浅。
通过这些解释我这个菜鸟也来说说领悟到的关于进程和线程的区别,不知是否正确,还请高手和大虾们指点,先谢了。
eg:进程:我们WINDOWS系统下word和excel,他们分别是windows OS下的两个进程。
   线程:在同一时刻开启的两个word或两个excel文档就是各自进程下的两个线程了。

以上验证可以通过windows的任务管理器观察开启进程和线程的变化,如内存变化。

出0入0汤圆

发表于 2010-10-13 16:24:52 | 显示全部楼层
进程是不共用内存的
线程是在同一片内存里面的的

出0入0汤圆

发表于 2010-12-24 19:59:45 | 显示全部楼层
讨论的挺好

出0入0汤圆

发表于 2011-1-23 05:00:47 | 显示全部楼层
记得我mark过了,再次mark。支持36楼:
eg:进程:我们WINDOWS系统下word和excel,他们分别是windows OS下的两个进程。
   线程:在同一时刻开启的两个word或两个excel文档就是各自进程下的两个线程了。

出0入0汤圆

发表于 2011-1-23 10:27:05 | 显示全部楼层
linux下编程就是Fork()和Ptheard的区别。

出0入0汤圆

发表于 2011-5-16 15:18:17 | 显示全部楼层
回复【39楼】xizi  
记得我mark过了,再次mark。支持36楼:
eg:进程:我们windows系统下word和excel,他们分别是windows os下的两个进程。
   线程:在同一时刻开启的两个word或两个excel文档就是各自进程下的两个线程了。

-----------------------------------------------------------------------

word确实产生一个进程。 好多别的程序都是打开几个几个进程。比如QQ

出0入0汤圆

发表于 2011-5-16 15:39:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-2 00:36:10 | 显示全部楼层
gzhuli 咕唧霖 正解

15楼的用例子说明,但是不太恰当

liuweiele Liuwei 自己实现了一个操作系统,的确是个MMU使用的不错的教程,从中也可以理解到进程概念。一直准备好好学习一下,等待他的开源。看样子代码规模比ucosII大,比linux小得多也容易理解的多

clingos 理解还是有些偏颇

djyos 都江堰操作系统 关于.net的抢先说法根本不靠谱,虚拟机上的东西和djy无关。

出0入0汤圆

发表于 2011-7-2 01:00:27 | 显示全部楼层
顺便说一下
djyos的“虚拟机”不是java或.net的虚拟机概念

出0入0汤圆

发表于 2011-9-28 13:49:23 | 显示全部楼层
最基本的区别就是进程之间地址空间是独立的,而线程之间是共享的。
不具备MMU的MCU理论上跑的都是线程。

学习了

出0入0汤圆

发表于 2011-11-6 22:55:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-6 23:31:23 | 显示全部楼层
简单说来,进程就是运行中的程序。是为了在CPU上实现多道编程而发明的一个概念。但是一个进程在一个时间只能干一件事情。如果想同时干两件事,那就又发明了线程。线程就是为了让一个进程能够同时干多件事情而发明的“分身术”。
    在线程模式下,一个进程至少有一个线程,但也可以有多个线程。
    线程就是进程的分身,每个线程在本质上是一样的,即拥有同样的程序文本。但因为是分身,也有不一样的地方,这就是线程执行时的上下文不一致。事实上,我们说线程是进程里面的一个执行上下文,或者执行序列。

出0入0汤圆

发表于 2011-11-20 21:27:03 | 显示全部楼层
好贴,mark

出0入0汤圆

发表于 2011-12-10 14:43:43 | 显示全部楼层
学习了

出0入0汤圆

发表于 2013-8-4 10:51:12 | 显示全部楼层
学习了,标记
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 16:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表