inux下一个进程包括是“数据段”,“堆栈段”和“代码段”,一个程序一调用fork函数,系统将创建一个与父进程完全一样的新的进程。但是,子进程一旦开始运行, 虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不 再共享任何数据了。而如果两个进程要共享什么数据的话,就要使用另一套函数(shmget,shmat,shmdt等) 来操作。对于父进程,fork函数返回了子程序的进程号,而对于子程序,fork函数 则返回零,这样,对于程序,只要判断fork函数的返回值,就知道自己是处于父进程还是子进程中。
比如对于以下代码:
pid_t pid=fork();
if(pid=0){xxx}
if(pid!=0){xxx}
由于子程序拷贝了这些代码和数据,因此都fork之前的代码都要执行两遍,之后父进程的fork函数创建一个子进程,返回子进程id,而子进程执行fork函数时不会再创建新的子进程,返回值是0,这样,通过if,下面{}之间的代码就有了区别;之后的代码也执行两边;
一般CPU都是以“页”为单位分配空间的, 象INTEL的CPU,其一页在通常情况下是4K字节大小,而无论是数据段还是堆栈段都是由许多“页”构成的, fork函数复制这两个段,只是“逻辑”上的,并非“物理”上的,也就是说,实际执行fork时,物理空间上两个进程的数据段和堆栈段都还是共享着的,当有一个进程写了某个数据时,这时两个进程之间的数据才有了区 别,系统就将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到最小。
一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,废弃原有的 数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言, 还是同一个进程,不过已经是另一个程序了。(不过exec类函数中有的还允许继承环境变量之类的信息。)
WIN32里的进程/线程是继承自OS/2的。在WIN32里,“进程”是指一个程序,而“线程”是一个“进程” 里的一个执行“线索”。在WIN32里的线程才相当于UNIX 的进程,是一个实际正在执行的代码。但是,WIN32里同一个进程里各个线程之间是共享数据段的。这才是与 UNIX的进程最大的不同。
在WIN32下,使用CreateThread函数创建线程,全局变量是子线程与父线程共享的,这就是与UNIX最大的不同之处。在UNIX里要实现类似WIN32的线程并不难,只要fork以后,让子进程调用ThreadProc函数,并且为全局变量开设共享数据区就行了,但在WIN32下就无法实现类似fork的功能了。
对于多任务系统,共享数据区是必要的,但也是一个容易引起混乱的问题,在WIN32下,一个程序员很容易忘记线程之间的数据是共享的这一情况,一个线程修改过一个变量后,另一个线程却又修改了它,结果引起程序出问题。但在UNIX下,由于变量本来并不共享,而由程序员来显式地指定要共享的数据,使程序变得更清晰与安全。至于WIN32的“进程”概念,其含义则是“应用程序”,也就是相当于UNIX下的exec了。
,POSIX标准提出了有名信号量和无名信号量的概念,Linux只实现了无名信号量
int sem_init(sem_t *sem,int pshared,unsigned int value); sem_init创建一个信号灯,并初始化其值为value.pshared决定了信号量能否在几个进程间共享.由于目前Linux还没有实现进程间共享信号灯,所以这个值只能够取0
Linux实现了System V信号量.