预览加载中,请您耐心等待几秒...
1/6
2/6
3/6
4/6
5/6
6/6

在线预览结束,喜欢就下载吧,查找使用更方便

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

Linux下的多进程编程 一)理解Linux下进程的结构 Linux下一个进程在内存里有三部份的数据,就是“数据段”,“堆栈段”和“代码段 ”,其实学过汇编语言的人一定知道,一般的CPU象I386,都有上述三种段寄存器,以方便 操作系统的运行。“代码段”,顾名思义,就是存放了程序代码的数据,假如机器中有数 个进程运行相同的一个程序,那么它们就可以使用同一个代码段。 堆栈段存放的就是子程序的返回地址、子程序的参数以及程序的局部变量。而数据段 则存放程序的全局变量,常数以及动态数据分配的数据空间(比如用malloc之类的函数取 得的空间)。这其中有许多细节问题,这里限于篇幅就不多介绍了。系统如果同时运行数 个相同的程序,它们之间就不能使用同一个堆栈段和数据段。 (二)如何使用fork 在Linux下产生新的进程的系统调用就是fork函数,这个函数名是英文中“分叉”的意 思。为什么取这个名字呢?因为一个进程在运行中,如果使用了fork,就产生了另一个进 程,于是进程就“分叉”了,所以这个名字取得很形象。下面就看看如何具体使用fork, 这段程序演示了使用fork的基本框架: voidmain(){ inti; if(fork()==0){ /*子进程程序*/ for(i=1;i<1000;i++) printf("Thisischildprocess\n"); } else{ /*父进程程序*/ for(i=1;i<1000;i++) printf("Thisisprocessprocess\n"); } } 程序运行后,你就能看到屏幕上交替出现子进程与父进程各打印出的一千条信息了。 如果程序还在运行中,你用ps命令就能看到系统中有两个它在运行了。 那么调用这个fork函数时发生了什么呢?一个程序一调用fork函数,系统就为一个新 的进程准备了前述三个段,首先,系统让新的进程与旧的进程使用同一个代码段,因为它 们的程序还是相同的,对于数据段和堆栈段,系统则复制一份给新的进程,这样,父进程 的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切 数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享 任何数据了。而如果两个进程要共享什么数据的话,就要使用另一套函数(shmget,shma t,shmdt等)来操作。现在,已经是两个进程了,对于父进程,fork函数返回了子程序的 进程号,而对于子程序,fork函数则返回零,这样,对于程序,只要判断fork函数的返回 值,就知道自己是处于父进程还是子进程中。 读者也许会问,如果一个大程序在运行中,它的数据段和堆栈都很大,一次fork就要 复制一次,那么fork的系统开销不是很大吗?其实UNIX自有其解决的办法,大家知道,一 般CPU都是以“页”为单位分配空间的,象INTEL的CPU,其一页在通常情况下是4K字节大小 ,而无论是数据段还是堆栈段都是由许多“页”构成的,fork函数复制这两个段,只是“ 逻辑”上的,并非“物理”上的,也就是说,实际执行fork时,物理空间上两个进程的数 据段和堆栈段都还是共享着的,当有一个进程写了某个数据时,这时两个进程之间的数据 才有了区别,系统就将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到 最小。 一个小幽默:下面演示一个足以"搞死"Linux的小程序,其源代码非常简单: voidmain() { for(;;)fork(); } 这个程序什么也不做,就是死循环地fork,其结果是程序不断产生进程,而这些进程 又不断产生新的进程,很快,系统的进程就满了,系统就被这么多不断产生的进程"撑死了 "。用不着是root,任何人运行上述程序都足以让系统死掉。哈哈,但这不是Linux不安全 的理由,因为只要系统管理员足够聪明,他(或她)就可以预先给每个用户设置可运行的 最大进程数,这样,只要不是root,任何能运行的进程数也许不足系统总的能运行和进程 数的十分之一,这样,系统管理员就能对付上述恶意的程序了。 (三)如何启动另一程序的执行 下面我们来看看一个进程如何来启动另一个程序的执行。在Linux中要使用exec类的函 数,exec类的函数不止一个,但大致相同,在Linux中,它们分别是:execl,execlp,ex ecle,execv,execve和execvp,下面我只以execlp为例,其它函数究竟与execlp有何区别 ,请通过manexec命令来了解它们的具体情况。 一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序 的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留