《unix高级环境编程》进程控制——exec序列函数
来源:互联网 发布:steam skyline 源码 编辑:程序博客网 时间:2024/05/17 08:24
exec 替换进程映像
在进程的创建上 UNIX 采用了一个独特的方法,它将进程创建与加载一个新进程映象分离,这样可以方便对两种操作进行管理。当创建了一个进程之后,通常可以用 exec 系列的函数将子进程替换成新的进程映象。当然,exec 系列的函数也可以将当前进程替换掉。
exec 序列函数
fork 函数创建一个子进程时,几乎复制了父进程的全部内容。exec 序列函数可以在一个在进程中启动另一个程序的执行,它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程 ID 未改变( exec 序列函数不创建新进程),其他全部被新的程序替换了。
在 Linux 中使用 exec 序列函数主要有两种情况:
- 当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用 exec 序列函数中的任意一个函数让自己重生。
- 如果一个进程想执行另一个程序,那么它就可以调用 fork 函数新建一个进程,然后调用 exec 序列函数中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程(这种情况非常普遍)。
- /* exec 序列函数 */
- /*
- * 函数功能:把当前进程替换为一个新的进程,新进程与原进程ID相同;
- * 返回值:若出错则返回-1,若成功则不返回;
- * 函数原型:
- */
- #include <unistd.h>
- int execl(const char *pathname, const char *arg, ...);
- int execv(const char *pathnam, char *const argv[]);
- int execle(const char *pathname, const char *arg, ... , char *const envp[]);
- int execve(const char *pathnam, char *const argv[], char *const envp[]);
- int execlp(const char *filename, const char *arg, ...);
- int execvp(const char *filename, char *const argv[]);
- 查找方式:前4个函数的查找方式都是完整的文件目录路径 pathname ,而最后两个函数(也就是以p结尾的两个函数)可以只给出文件名 filename,系统就会自动按照环境变量 “$PATH” 所指定的路径进行查找。
- 参数传递方式:exec 序列函数的参数传递有两种方式:一种是逐个列举的方式,而另一种则是将所有参数整体构造指针数组传递。在这里是以函数名的第5位字母来区分的,字母为 “l”(list)的表示逐个列举参数的方式,其语法为 const char *arg;字母为 “v”(vertor)的表示将所有参数整体构造指针数组传递,其语法为 char *const argv[]。读者可以观察 execl()、execle()、execlp() 的语法与 execv()、execve()、execvp() 的区别。这里的参数实际上就是用户在使用这个可执行文件时所需的全部命令选项字符串(包括该可执行程序命令本身)。要注意的是,这些参数必须以NULL结束。
- 环境变量:exec 序列函数可以默认系统的环境变量,也可以传入指定的环境变量。这里以 “e”(environment)结尾的两个函数 execle() 和 execve() 就可以在 envp[] 中指定当前进程所使用的环境变量。
- 表 1 exec 序列函数的总结
- 前4位 统一为:exec
- 第5位 l:参数传递为逐个列举方式 execl、execle、execlp
- v:参数传递为构造指针数组方式 execv、execve、execvp
- 第6位 e:可传递新进程环境变量 execle、execve
- p:可执行文件查找方式为文件名 execlp、execvp
- 找不到文件或路径,此时 errno 被设置为 ENOENT。
- 数组 argv 和 envp 忘记用NULL结束,此时,errno 被设置为 EFAUL。
- 没有对应可执行文件的运行权限,此时 errno 被设置为EACCES。
- /* 执行exec函数,下面属性是不发生变化的:
- *进程ID和父进程ID(pid, ppid)
- *实际用户ID和实际组ID(ruid, rgid)
- *附加组ID(sgid)
- *会话ID
- *控制终端
- *闹钟余留时间
- *当前工作目录
- *根目录
- *umask
- *文件锁
- *进程信号屏蔽
- *未处理信号
- *资源限制
- *进程时间
- */
- /*而下面属性是发生变化的:
- *文件描述符如果存在close-on-exec标记的话,那么打开的文件描述符会被关闭。
- *如果可执行程序文件存在SUID和SGID位的话,那么有效用户ID和组ID(euid, egid)会发生变化
- */
测试程序:
- #include "apue.h"
- #include <unistd.h>
- #include <sys/wait.h>
- char *argv[] = {"echo", "STATUS=testing", "\tHellow linux","\tgood bye",NULL};
- char *argve[] = {"env",NULL};
- char *env[] = {"USER=unknown", "PATH=/tmp",NULL};
- int main()
- {
- pid_t pid;
- if((pid = fork()) < 0) /* fork error */
- err_sys("fork error.");
- else if(0 == pid) /* in child process */
- {
- if(execl("/bin/ls","ls","-a", "-l", (char *)0) == -1)
- err_sys("execl error.\n");
- // exit(0);
- }
- if(waitpid(pid, NULL, 0) < 0)
- err_sys("wait error.");
- if((pid = fork()) < 0) /* fork error */
- err_sys("fork error.");
- else if(0 == pid) /* in child process */
- {
- if(execlp("ls","ls","-a", "-l", (char *)0) == -1)
- err_sys("execlp error.\n");
- // exit(0);
- }
- if(waitpid(pid, NULL, 0) < 0)
- err_sys("wait error.");
- if((pid = fork()) < 0) /* fork error */
- err_sys("fork error.");
- else if(0 == pid) /* in child process */
- {
- if(execvp("echo", argv) == -1)
- err_sys("execvp error.\n");
- }
- if(waitpid(pid, NULL, 0) < 0)
- err_sys("wait error.");
- if((pid = fork()) < 0) /* fork error */
- err_sys("fork error.");
- else if(0 == pid) /* in child process */
- {
- if(execve("/usr/bin/env", argve, env) == -1)
- err_sys("execve error.\n");
- }
- exit(0);
- }
输出结果:
- total 24
- drwxrwxr-x 2 nifengweijifen nifengweijifen 4096 Nov 7 15:07 .
- drwxrwxr-x 3 nifengweijifen nifengweijifen 4096 Nov 7 15:07 ..
- -rwxrwxr-x 1 nifengweijifen nifengweijifen 12348 Nov 7 15:07 exec
- -rw-rw-r-- 1 nifengweijifen nifengweijifen 0 Nov 7 14:43 exec.c
- -rw-rw-r-- 1 nifengweijifen nifengweijifen 0 Nov 7 14:43 exectest.c
- total 24
- drwxrwxr-x 2 nifengweijifen nifengweijifen 4096 Nov 7 15:07 .
- drwxrwxr-x 3 nifengweijifen nifengweijifen 4096 Nov 7 15:07 ..
- -rwxrwxr-x 1 nifengweijifen nifengweijifen 12348 Nov 7 15:07 exec
- -rw-rw-r-- 1 nifengweijifen nifengweijifen 0 Nov 7 14:43 exec.c
- -rw-rw-r-- 1 nifengweijifen nifengweijifen 0 Nov 7 14:43 exectest.c
- STATUS=testing Hellow linux good bye
- USER=unknown
- PATH=/tmp
0 0
- 《unix高级环境编程》进程控制——exec序列函数
- 《unix高级环境编程》进程控制——exec序列函数
- 《unix高级环境编程》进程控制——system函数
- 《unix高级环境编程》进程控制——system函数
- 《unix高级环境编程》进程控制——进程ID
- 《unix高级环境编程》进程控制——创建进程
- 《unix高级环境编程》进程控制——进程等待
- 《unix高级环境编程》进程控制——进程时间
- 《unix高级环境编程》进程控制——进程ID
- 《unix高级环境编程》进程控制——创建进程
- 《unix高级环境编程》进程控制——进程等待
- 《unix高级环境编程》进程控制——进程时间
- UNIX环境高级编程——进程控制
- Unix高级环境编程—进程控制(一)
- Unix环境高级编程—进程控制(二)
- Unix环境高级编程—进程控制(三)
- unix环境高级编程----进程控制fock()函数
- 《unix高级环境编程》进程关系——控制终端、作业控制和守护进程
- The connection to adb is down, and a severe error has occured.
- Java文件下载
- wampmanager配置多版本php,apache
- 冯诺依曼结构和哈佛结构
- 13周。。项目六。。文件输入。。处理成绩(3)
- 《unix高级环境编程》进程控制——exec序列函数
- 一次分布式数据采集中的MSSQLSERVER技术总结
- 设备节点创建过程源代码分析
- 发明专利申请的一些内容
- sdk改变ListCtrl某一行的字体颜色或者背景颜色
- 破坏城市
- 第13周 项目1-5 向数组内插入元素
- SDUTOJ 1463 C++与Java
- 《unix高级环境编程》进程控制——解释器文件