免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 21887 | 回复: 34
打印 上一主题 下一主题

fork、exec系列与system、popen区别 [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-05-06 19:52 |只看该作者 |倒序浏览
两个问题,请大家一起讨论。


1、fork和exec系列调用前后,进程在内存的“数据段”,“堆栈段”和“代码段”有什么不同?除此以外,fork和exec系列调用还有什么区别?



2、system和popen有什么区别?都常用在什么场合?

论坛徽章:
0
2 [报告]
发表于 2003-05-06 20:00 |只看该作者

fork、exec系列与system、popen区别

文件描述字在fork和exec中都是保持打开的
我学理这个比较重要

论坛徽章:
0
3 [报告]
发表于 2003-05-06 20:01 |只看该作者

fork、exec系列与system、popen区别

有点跑题了
但是还是请大家思考一下其它比较重要的地方

论坛徽章:
0
4 [报告]
发表于 2003-05-06 22:42 |只看该作者

fork、exec系列与system、popen区别

对于fork():
1、子进程复制父进程的所有进程内存到其内存地址空间中。父、子进程的
“数据段”,“堆栈段”和“代码段”完全相同,即子进程中的每一个字节都
  和父进程一样。
2、子进程的当前工作目录、umask掩码值和父进程相同,fork()之前父进程
  打开的文件描述符,在子进程中同样打开,并且都指向相同的文件表项。
3、子进程拥有自己的进程ID。

对于exec():
1、进程调用exec()后,将在同一块进程内存里用一个新程序来代替调用
  exec()的那个进程,新程序代替当前进程映像,当前进程的“数据段”,
“堆栈段”和“代码段”背新程序改写。
2、新程序会保持调用exec()进程的ID不变。
3、调用exec()之前打开打开的描述字继续打开(好像有什么参数可以令打开
  的描述字在新程序中关闭)

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
5 [报告]
发表于 2003-05-07 09:28 |只看该作者

fork、exec系列与system、popen区别

1、fork()
    一个程序一调用fork函数,系统就为一个新的进程准备了前述三个段,首先,系统让新的进程与旧的进程使用同一个代码段,因为它们的程序还是相同的,对于数据段和堆栈段,系统则复制一份给新的进程,这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。而如果两个进程要共享什么数据的话,就要使用另一套函数(shmget,shmat,shmdt等)来操作。现在,已经是两个进程了,对于父进程,fork函数返回了子程序的进程号,而对于子程序,fork函数则返回零,这样,对于程序,只要判断fork函数的返回值,就知道自己是处于父进程还是子进程中。

   事实上,目前大多数的unix系统在实现上并没有作真正的copy。一般的,CPU都是以“页”为单位分配空间的,象INTEL的CPU,其一页在通常情况下是4K字节大小,而无论是数据段还是堆栈段都是由许多“页”构成的,fork函数复制这两个段,只是“逻辑”上的,并非“物理”上的,也就是说,实际执行fork时,物理空间上两个进程的数据段和堆栈段都还是共享着的,当有一个进程写了某个数据时,这时两个进程之间的数据才有了区
别,系统就将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到最小。

2、对于exec系列函数
    一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。不过exec类函数中有的还允许继承环境变量之类的信息,这个通过exec系列函数中的一部分函数的参数可以得到。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
6 [报告]
发表于 2003-05-07 12:41 |只看该作者

fork、exec系列与system、popen区别

子进程继承了父进程的几乎所有的属性,包括如下: 
. 实际UID,GID和有效UID,GID. 
. 环境变量. 
. 附加GID. 
. 调用exec()时的关闭标志. 
. UID设置模式比特位. 
. GID设置模式比特位. 
. 进程组号. 
. 会话ID. 
. 控制终端. 
. 当前工作目录. 
. 根目录. 
. 文件创建掩码UMASK. 
. 文件长度限制ULIMIT. 
. 预定值, 如优先级和任何其他的进程预定参数, 根据种类不同决定是否可以继承. 
. 还有一些其它属性. 


但子进程也有与父进程不同的属性,这点很重要:
. 进程号, 子进程号不同与任何一个活动的进程组号. 
. 父进程号. 
. 子进程继承父进程的文件描述符或流时,具有自己的一个拷贝并且与父进程和其它子进程共享该资源. 
. 子进程的用户时间和系统时间被初始化为0. 
. 子进程的超时时钟设置为0. 
. 子进程的信号处理函数指针组置为空. 
. 子进程不继承父进程的记录锁. 

论坛徽章:
0
7 [报告]
发表于 2003-05-07 12:56 |只看该作者

fork、exec系列与system、popen区别

上面这些比较重要

同时编程中也应该注意是继承了什么内容
如不用的文件描述符在fork后应该关闭

论坛徽章:
0
8 [报告]
发表于 2003-05-07 17:06 |只看该作者

fork、exec系列与system、popen区别

基本上 fork + exec = system()

比如你的一个进程想运行几个外部程序, 比如sqlplus什么的。 可以fork子进程, 然后在子进程中exec(sqlplus)

我觉得基本和在你的进程中调用system()差不多, 更灵活? 谁给说说看。

论坛徽章:
0
9 [报告]
发表于 2003-05-07 17:51 |只看该作者

fork、exec系列与system、popen区别

使用system不是很安全,并且需要起一个shell
增加系统开锁

论坛徽章:
0
10 [报告]
发表于 2003-06-26 11:18 |只看该作者

fork、exec系列与system、popen区别

原帖由 "蓝色键盘" 发表:

1、fork()
    一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。不过exec类函数中有的还允许继承环境变量之类的信息,这个通过exec系列函数中的一部分函数的参数可以得到。
   

如键盘兄所述,exec 会代替原先的进程,但是为什么exec之后,仍然可以返回呢?

比如下面的程序,在第一个exec后,程序仍然可以继续运行。无论是出错处理或者是再执行下一个exec,表现都非常棒。

请教一下,是不是在exec时,系统仍然为进程设置了堆栈以保存原来进程的所有信息呢?是由内核实现的吗?与平常的function有什么不同呢?

如果我理解正确的话,我想这个也能算是exec与fork的区别之一:exec时,内核需要保存堆栈.fork时,内核不需要保存堆栈。

如果上面的说法正确的话,那么exec一定比fork要慢。
因为fork时,系统只要拷贝子进程的一次。而exec时,首先要把原来进程入栈,另外还需要把新进程拷贝到原来的进程之中。
当exec返回时,还有一个原来进程出栈的操作,也需要切换到内核态执行。

其三,如果exec的进程比原进程要大的话,还需要重新申请内存。如果比原来进程要小得多的话,是不是也浪费了相当多的内存?

请键盘和无双两位老大多多指教呀。

还有个建议,这个帖子应该加精的。大家好查看的。

  1. #include        <sys/types.h>;
  2. #include        <sys/wait.h>;
  3. #include        "ourhdr.h"

  4. char    *env_init[] = { "USER=unknown", "PATH=/tmp", NULL };

  5. int
  6. main(void)
  7. {
  8.         pid_t   pid;

  9.         if ( (pid = fork()) < 0)
  10.                 err_sys("fork error");
  11.         else if (pid == 0) {    /* specify pathname, specify environment */
  12.                 if (execle("/usr/home/mike/study/C/APUE/echoarg",
  13.                                    "echoarg", "myarg1", "MY ARG2", (char *) 0,
  14.                                    env_init) < 0)
  15.                         err_sys("execle error");
  16.         }
  17.         if (waitpid(pid, NULL, 0) < 0)
  18.                 err_sys("wait error");

  19.         if ( (pid = fork()) < 0)
  20.                 err_sys("fork error");
  21.         else if (pid == 0) {    /* specify filename, inherit environment */
  22.                 if (execlp("echoarg",
  23.                                    "echoarg", "only 1 arg", (char *) 0) < 0)
  24.                         err_sys("execlp error");
  25.         }
  26.         exit(0);
  27. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP