linux 进程学习笔记-运行新进程
我们知道,当用fork启动一个新进程以后,新进程会复制父进程的大部份内存空间并接着运行父进程中的代码,如果我们使新进程不运行原父进程的代码,转而运行另外一个程序集中的代码,这就相当于启动了一个新程序。
所以,要运行一个新程序,需要最基本的两步:
Ÿ 创建一个可运行程序的环境,也就是进程。
Ÿ 将环境中的内容替换成你所希望的,也就是用你希望运行的可执行文件去覆盖新进程中的原有映像,并从该可执行文件的起始处开始执行。
要做到第一点,非常简单,fork函数就可以;而要做到第二点,则可以利用exec函数族。
exec是一族函数的简称,包含在<unistd.h>中,它们作用都一样,用一个可执行文件覆盖进程的现有映像,并转到该可执行文件的起始处(main)开始执行。
原型如下:
int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
int execle(const char *path, const char *arg0, ... /*, (char *)0, char *const envp[]*/);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
我们先以最简单的execl函数为例,其他的大同小异。其第一个参数path是可执行文件的路径,是绝对路径;从arg0参数开始及后面所有的是你要传递给可执行文件的命令行参数。最后有一个注释/*, (char*)0 */是提醒我们最后一个参数应该传空字符串。如何函数运行成功,则不会有任何返回值,否则返回-,而具体的错误号会被设置在errno,errno是一个全局变量,用于程序设置错误号。
看下面的例子:
#include <stdio.h>
#include <unistd.h>
int main ()
{
printf("app start...\n");
execl("/bin/ls", "/bin/ls", "-l",NULL);
printf("app end\n");
return ;
}
我们运行了bin目录下的ls程序,参数arg0时ls程序本身路径,arg1为-l,使得其以列表的形式列举当前目录,在我的计算机上程序输出如下:
app start...
total
-rw-r--r-- zhouyh zhouyh -- : temp.c
-rwxr-xr-x zhouyh zhouyh -- : temp.exe
ls程序运行成功了。
但注意到了吗?没有输出“app end”这个字符串,原因很简单,我们没有新起进程,而是直接用ls程序覆盖了main函数所在的进程。
如果我们使用fork先启一个新进程,当其成功创建后(返回值为0),我们用execl来加载ls程序到新进程并运行之:
#include <stdio.h>
#include <unistd.h>
int main ()
{
printf("app start...\n");
if(fork() == )
{
execl("/bin/ls", "/bin/ls", "-l", NULL);
}
printf("app end\n");
return ;
}
程序的输出如下:
app start...
app end
zhouyh@ubuntu:~/Documents$ total
-rw-r--r-- zhouyh zhouyh -- : temp.c
-rwxr-xr-x zhouyh zhouyh -- : temp.exe
程序的所有输出都OK了,但有一点可能和我们想象的不一样,那就是“app end”这个字符串很早就输出了而不是在最后,其实这并没有错,“app end” 是main函数所在的程序(temp.exe)即将结束时输出的,而列举文件目录的ls却完全在另外一个进程中,两个异步执行的进程,它们没有谁先谁后结束可言。(如果我们希望所有工作完成之后,即ls也执行玩以后,才输出“app end”,那么可以使用wait以及waitpid函数,“进程控制”中会讲,也可以参考我的
现在回过头来看除execl外的其他几个函数 :
int execlp (const char *file, const char *arg0, ... /*, (char *)0 */);
execlp和execl差不多,但区别在于前者会去系统环境变量查找file所指的程序的位置,所以如果通过环境变量能找到可执行文件,则file可以不是绝对路径了,比如 execlp("ls", "ls", "-l", NULL);
int execle (const char *path, const char *arg0, ... /*, (char *)0, char *const envp[]*/);
与execlp不同的是,其最后一个参数作为你自定义的环境变量参数传进去,而不是查找系统环境变量
char *env[] = { "HOME=/usr/home", "LOGNAME=home",(char *) };
execle("/bin/ls", "ls", "-l", NULL, env);
int execv (const char *path, char *const argv[]);
int execvp (const char *file, char *const argv[]);
int execve (const char *path, char *const argv[], char *const envp[]);
这三个函数和前面的三个类似,函数名由后缀l变成了v,其表达的含义是参数不再用参数列表传递而是用一个参数数组argv[],当然,数组最后一个元素也必须是char*
名字这么相近的函数,很容易混淆,可以从l,v,p,e 这样的后缀来区分:
l:参数为一个逗号分隔的参数列表,并以char* 0作为列表结尾
v: 参数为字符串数组,数组的最后一个元素为char*
p: 可以通过系统环境变量查找文件位置
e:调用者显示传入环境变量
linux 进程学习笔记-运行新进程的更多相关文章
- Linux内核学习笔记-2.进程管理
原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
- linux 进程学习笔记-进程调度
在分时系统中,系统将CPU时间划分成无数个时间片(quantum)分配给不同的进程,一个时间片只执行一个进程,并且不停地切换,以让用户感觉到各个进程是在“同时运行”,这中间所需要的策略和算法便是进程调 ...
- Linux查看非root运行的进程
Linux查看非root运行的进程 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ ps -U root -u root -N PID TTY TIME CMD ...
- Linux查看当前正在运行的进程
Linux查看当前正在运行的进程 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ ps PID TTY TIME CMD 2576 pts/0 00:00:00 ...
- C++学习笔记42:进程管理
子进程异步清除 SIGCHLD信号:子进程终止时,向父进程自动发送,编写此信号处理例程,异步清除子进程 #include <signal.h> #include <string.h& ...
- 在Linux上显示正在运行的进程的线程ID
在Linux上显示正在运行的进程的线程ID 在上Linux," ps -T"可以显示正在运行的进程的线程信息: # ps -T 2739 PID SPID TTY STAT TIM ...
- linux kernel学习笔记-5内存管理_转
void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...
- 尚硅谷韩顺平Linux教程学习笔记
目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...
随机推荐
- sql 时间相关
1.常用日期方法(下面的GetDate() = '2006-11-08 13:37:56.233') (1)DATENAME ( datepart ,date ) 返回表示指定日期的指定日期部分的字符 ...
- DeepinXP Lite 6.2 精简版220M 安装IIS
本作品由Man_华创作,采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可.基于http://www.cnblogs.com/manhua/上的作品创作. 用虚拟机装了DEEP ...
- mysql经常使用查询:group by,左连接,子查询,having where
前几天去了两个比較牛的互联网公司面试.在sql这块都遇到问题了,哎.可惜呀,先把简单的梳理一下 成绩表 score 1.group by 使用 按某一个维度进行分组 比如: 求每一个同学的总分 SEL ...
- mysql解决中文乱码
mysql>use mydb; mysql>alter database mydb character set utf8;! 这种方法只对设置后重新创建的表有效,对已存在的表无效 des ...
- 【问】Windows下C++局部变量在内存中的分布问题
原本是为了看看C++对象模型中子对象赋值给一个父对象和父类型指针指向的域时,到底会不会切割,就打开codebloks写了下面的代码,编译器选的是GNU. #define DEBUG(X) std::c ...
- HTML5实现两个视频循环播放!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- go的timer定时器实现
示例如下: package main import ( "fmt" "time" ) func testTimer1() { go func() { fmt.P ...
- 15 nginx反向代理实现nginx+apache动静分离
一:nginx反向代理实现nginx+apache动静分离-------------概念--------------------------- nginx反向代理服务器+负载均衡 用nginx做反向代 ...
- Using ADO.NET Data Service
ADO.NET Data Service是随同Visual Studio 2008 SP1提供的用于构建在数据对象模型 (如EF-DEMX, LINQ-DBML) 之时来快速提供企业网内外的轻量级数据 ...
- 新西兰天维网登录发送明文password
新西兰比較有人气的华人社区站点是天维网(新西兰天维网),是这边华人用中文吐槽常常上的论坛,也是华人之间各种交易(比方买卖二手车)的集散地.上次非诚勿扰新西兰专场就是天维网承办的宣传和报名.来新西兰定居 ...