进程创建方式与exec函数簇
2016-06-08 11:30
162 查看
[align=left]进程的两个基本元素:[/align]
[align=left]1、程序代码;[/align]
[align=left]2、与代码相关联的数据集[/align]
[align=left]**********************************************************************************************************[/align]
[align=left]一、要创建一个子进程可以执行fork()系统调用。[/align]
[align=left] 返回值:成功的话,有两个返回值(子进程->0,父进程->子进程的 id);失败返回 -1.[/align]
[align=left]子进程与父进程的关系:数据独立,代码共享。[/align]
[align=left]子进程会得到父进程中数据段,栈段和堆区域的一份拷贝。子进程独立可以修改这些内存段(但这些都是当有进程要对这些区域里的数据进行修改时,拷贝才会发生)。但是文本段是父进程和子进程共享的内存段,不能被子进程修改。[/align]
[align=left]
[/align]
[align=left]fork成功后,父子进程的执行顺序是不确定的,是由内核的调度算法决定的。[/align]
[align=left]fork的一个特性:父进程的所有打开文件描述符都被复制到子进程中。父子进程的每个相同的打开描述符共享一个文件表项[/align]
[align=left]
[/align]
[align=left]fork有下面两种用法:[/align]
[align=left]1、父进程希望子进程执行自己的一个代码分支[/align]
[align=left]2、fork成功后,调用exec函数簇,执行其它的代码(进程的程序替换)[/align]
[align=left]
[/align]
[align=left]fork调用失败的原因:[/align]
[align=left]1、系统中有太多的进程[/align]
[align=left]2、实际用户的进程数超过了限制[/align]
父子进程之间的区别:
1. fork的返回值
2.
进程ID
不同
3.
具有不同的父进程ID
4.
子进程的tms_utime
、tms_stime、
tms_cutime及tms_ustime
均被设置为0
5.
父进程设置的文件锁不会被子进程继承
6.
子进程的未处理闹钟被清除
7.
子进程的未处理信号集被设置为空集
**********************************************************************************************************
[align=left]二、要创建一个子进程也可以执行vfork()系统调用。[/align]
[align=left]该函数的特点:[/align]
[align=left](1)父子进程会共享同一地址空间[/align]
(2)vfork在保证子进程先运行,它调用
exec或(exit)之后父进程才可能被调度运行
。
[align=left]注意:子进程不能以 return 结束,否则会死循环(return可能会修改程序计数器,使它又指向main函数的入口地址)[/align]
[align=left]**********************************************************************************************************[/align]
[align=left]三、exec进程程序替换[/align]
[align=left]
[/align]
当进程调用一种
exec函数时
,该进程的用户空间代码和数
据完全被新程序替换 ,从新程序的启动例程开始执行。调用
exec并不创建新进程
,所以调用
exec前 后该进程的
id并未改变。
其实有六种以
exec开头的函数
,统称
exec函数:
[align=left]#include <unistd.h>[/align]
[align=left]int execl(const char *path, const char *arg, ...);[/align]
[align=left]int execlp(const char *file, const char *arg, ...);[/align]
[align=left]int execle(const char *path, const char *arg, ..., char *const envp[]);[/align]
[align=left]int execv(const char *path, char *const argv[]);[/align]
[align=left]int execvp(const char *file, char *const argv[]);[/align]
[align=left]int execve(const char *path, char *const argv[], char *const envp[]);[/align]
这些函数如果调用成功则加载新的程序从启动代码开始执行
,不再返回
,如果调用出错则返回-1,
所以
exec函数只有出错的返回值,而没有成功的返回值。
[align=left]
[/align]
[align=left]
[/align]
不带字母
p(
表示path)
的exec
函数
第一个参数必须是程序的相对路径或绝对路径
,例如"/bin/ls"或
"./a.out",而不能 是
"ls"或
"a.out"。对于带字母
p的函数
:
如果参数中包含
/,则将其视为路径名。 否则视为不带路径的程序名
,在
PATH环境变量的目录列表中搜索这个程序。
[align=left]
[/align]
带有字母
l(表示
list)的
exec函数
要求将新程序的每个命令行参数都当作一个参数传给它,命令行参数的个数是可变的
,因此函数原型中有
...,...中的
最后一个可变参数应该是NULL,
起sentinel
的作用。
[align=left]
[/align]
带有字母
v(表示
vector)的函数
,则应该
先构造一个指向各参数的指针数 组
,然后将该数组的首地址当作参数传给它
,数组中的最后一个指针也应该是
NULL,
就像main
函数 的argv参数或者环境变量表一样。
[align=left]
[/align]
对于以e(表示environment)结尾的exec函数,可以把一份新的环境变量表传给它,其他exec函数
仍使用当前的环境变量表执行新程序。
[align=left]**********************************************************************************************************[/align]
[align=left]四、进行进程程序替换函数的应用举例[/align]
(1)int execl(const char *path, const char *arg,
...);
[align=left] 该程序的执行结果:父进程会输出:this is father process,子进程:会在 "/home/zhangdan/BIT_CLASS"下执行 "ls -al"命令[/align]
[align=left](2)int execlp(const char *file, const char *arg, ...); [/align]
[align=left] 该函数的使用与(1)类似,只是因为“p"的原因,有所改变。[/align]
[align=left] 如要实现(1)的功能,则上述第11行的 "/bin/ls"可改为”ls"(不改也可以)。[/align]
[align=left](3)int execv(const char *path, char *const argv[]);[/align]
[align=left](4)int execvp(const char *file, char *const argv[]);[/align]
[align=left] 该函数与(2)的修改方式一样,它是基于(3)可改变第一个参数。
[/align]
[align=left]
[/align]
相关文章推荐
- git fork同步是什么意思?
- Linux系统中C语言编程创建函数fork()执行解析
- python创建进程fork用法
- 小结Python用fork来创建子进程注意事项
- Python中的进程分支fork和exec详解
- fork, exec, source
- 使用 GDB 调试多进程程序
- Android架构纵横谈之二——基于性能的考虑
- linux下面fork 函数的详细讲解
- fork的执行过程
- fork()一次调用两次返回
- “Linux内核分析”实验报告(六)分析Linux内核创建一个新进程的过程
- Linux下嵌入汇编代码调用API(using fork())
- 分析system_call中断处理过程
- 进程知识点
- 英雄所见略同
- Head First C 第九章 进程与系统调用 用fork()+exec()运行子进程
- [Android]通过JNI实现卸载自身App后台发送Http请求~
- grails不能调试
- fork函数