linux c++多进程
来源:互联网 发布:梅露露 保存数据不存在 编辑:程序博客网 时间:2024/06/04 20:04
当我们看恐怖片时,经常会有这样的场景:当一个人被鬼上身后,这个人的身体表面上还和以前一样,但是他的灵魂和思想已经被这个鬼占有了,因此它会控制这个人做他自己想做的事情–那么在进程中也有这样的情景。那么是如何实现的呢?现在我们来学习exec()函数族
一.exec()函数 族
1. 首先我们在终端输入命令:man exec 可以看到函数的原型:
#include <unistd.h>
int execl(const char *path, const char *arg, …);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg,…, char * const envp[]);
int execve(const char*pathname, const char *argv[], char *const envp[]);
int execlp(const char *file, const char *arg, …);
int execvp(const char *file, char *const argv[]);
这些函数之间的第一个区别 是前4个取路径名做参数,后两个则取文件名做参数。
当指定filename做参数时:
a. 如果filename中包含/,则将其视为路径名
b. 否则就按PATH环境变量搜索可执行文件。
PATH=/bin:/usr/bin:/user/local/bin:.
最后的路径前缀表示当前目录。零前缀耶表示当前目录(在name=value开始处可用:表示,在中间用::表示,在行尾用:表示)
第二个区别 与参数表的传递有关(l表示list,v表示矢量vector)。函数execl、execlp和execle要求将新程序的每个命令行参数都说明为一个单独的参数,这中参数表以空指针结尾。而execv、execve和execvp则要先构造一个指向各参数的指针数组,然后将该数组的地址作为这三个函数的地址。
第三个区别 与向新程序传递环境表相关。函数execve和execle可以传递一个指向环境字符串指针数组的指针。
Tiger-John总结:
1>.其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
2>.exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容 ,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
但是若为Shell脚本时必须遵守以下的格式开头:
第一行必须为: #!interpretername[arg]。其中interpretername可以时 shell或其他解释器。例如,/bin/sh或/usr/bin/perl,arg是传递个解释器的参数。
3>记忆方法:
l : 表示使用参数列表(list)
e:表示使用新的环境变量,不从当前继承
p: 表示使用文件名,并从PATH环境进行搜索
4> exec()函数族成功后是不会返回值的,因为进程的执行映像已经被替换,没有接收返回值的地方了。但是若有一个错误的事件,将会返回-1.这些错误通常是有文件名或参数错误引起的。
2.exec()函数的功能:
1>exec()函数调用并没有生成新进程,一个进程一旦调用exec函数,它本省就“死亡了”–就好比被鬼上身一样,身体还是你的,但灵魂和思想已经被替换了 –系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一保留的就是进程ID。也就是说,对系统而言,还是同一个进程,不过执行的已经是另外一个程序了。
2>执行exec()函数后的进程除了保持了原来的进程ID,父进程ID,实际用户ID和实际组ID之外,进程还保持了其他许多原有特征,主要有
a.当前工作目录
b.根目录
c.创建文件时使用的屏蔽字
d.进程信号屏蔽字。
e. 未决警告
f.和进程相关的使用处理器的时间
g.控制终端
h.文件锁
Tiger-John说明:
1.此处要分清只有fork()或vfork()函数才能创建一个新进程,而exec()函数时不能创建进程的。
2.因此在使用exec()函数之前,先要使用fork()或vfork()创建子进程后,子进程调用exec()函数来执行另外一个程序。
3.exec()函数族的具体实现
1>当进程调用一种exec()函数时,该进程执行的程序完全替换为新程序,而新程序则从main函数开始执 行 。因为调用exec()并不创建新进程,所以前后的进程ID不变。函数exec()只是用一个全新的程序替换当前进程的正文、数据、堆和栈段。
2>无论是哪个exec()函数,都是将可执行程序的路径,命令行参数和环境变量3个参数传递个可执行程序的main()函数 。
3>具体介绍exec()函数族是如何main()函数需要的参数传递个它的。
a.execv()函数:execv()函数是通过路径名方式调用可执行文件作为新的进程映像。它的argv参数用来提供给main()函数的argv参数。argv参数是一个以NULL结尾的字符串数组
b.execve()函数:参数pathname时将要执行的程序的路径名,参数argv,envp 与main()函数的argv,envp对应 。
c.execl()函数:次函数与execv函数用法类似。只是在传递argv 参数的时候,每个命令行参数都声明为一个单独的参数(参数中使用“……”说明参数的个数是不确定的),要注意的是这些参数要以一个空指针作为结束。
d.execle()函数:该函数与execl函数用法类似,只是要显示指定环境变量。环境变量位于命令行参数最后一个参数的后面,也就是位于空指针之后。
e.execvp函数:该函数和execv函数用法类似,不同的是参数filename。该参数 如果包含/,则将其视为路径名,否则就按PATH环境变量搜索可执行文件。
f.execlp()函数:该函数于execl函数类似,它们的区别和execvp与execv的区别一样。
———————————————-
通过以上学习,我们来编个程序来体验下它的执行过程
4.函数实例
exec.c
#include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<stdlib.h> int main(int argc,char *argv[],char ** environ) { pid_t pid; int status; printf("Exec example!\n"); pid = fork(); if(pid < 0) { perror("Process creation failed\n"); exit(1); } else if(0 == pid) { printf("child process is running\n"); printf("My pid = %d ,parentpid = %d\n",getpid(),getpid()); printf("uid = %d,gid = %d\n",getuid(),getgid()); execve("processimage",argv,environ); printf("process never go to here!\n"); exit(0); } else { printf("Parent process is runnig\n"); } wait(&status); exit(0); }
processimage.c
#include<stdio.h> #include<sys/types.h> #include<unistd.h> int main(int argc,char * argv[],char ** environ) { int i; printf("I am a process image!\n"); printf("My pid =%d,parentpid = %d\n",getpid(),getppid()); printf("uid = %d,gid = %d\n",getuid(),getpid()); for(i = 0;i<argc;i++) { printf("argv[%d]:%s\n",i,argv[i]); } }
函数经过编译:
think@Ubuntu:~/work/process_thread/exec1
think@ubuntu:~/work/process_thread/exec1$ ./exec test exec
函数执行结果:
Exec example!
Parent process is runnig
child process is running
My pid = 5949 ,parentpid = 5949
uid = 1000,gid = 1000
I am a process image!
My pid =5949,parentpid = 5948
uid = 1000,gid = 5949
argv[0]:./exec
argv[1]:test
argv[2]:exec
Tiger-John说明:
1.通过上面程序的执行,我们可以看到执行新程序的进程保持了原来进程的进程ID,父进程ID,实际用户ID和实际组ID。
2. 当调用execve()函数后,原来的子进程的映像被替代,不再执行。
- linux多进程c编程
- linux c 多进程多线程比较
- Linux C 多进程下载文件demo
- Linux下C语言多进程实现
- [Linux C]多进程编程与进程间通信
- linux c 创建进程
- linux c 进程控制
- linux c 守护进程
- 【Linux C】进程环境
- 【Linux C】进程控制
- linux c 守护进程
- Linux c 开发 - 进程
- linux c 创建进程
- C语言-LINUX进程
- Linux C语言 进程
- Linux C进程、线程
- linux c 进程学习
- 【Linux】【C/C++】多进程协同词频统计
- 成为优秀的程序员的特质
- Java 多线程的创建 ---继承Thread类
- hdu 1848 Fibonacci again and again(nim博弈)
- android 第三方app截图
- Express 框架
- linux c++多进程
- JZOJ3426. 【NOIP2013模拟】封印一击 (2017.8B组)
- Vue.js知识总结——生命周期
- 初学oracle 第三天 体系结构
- 将输入字符串中的字符按如下规则排序。 规则 1 :英文字母从 A 到 Z 排列,不区分大小写
- 数字0-9的数量 数位dp
- markdown编辑器添加表格
- 设计模式——抽象工厂模式及在jdk中的应用+几种工厂模式的比较
- 静态和动态包含的区别与联系