进程的替换与复制

进程的替换

进程替换是指把当前进程替换为一个新的程序。替换进程使用 exec 系列函数。进程被exec 替换后,运行中的程序就开始执行由 exec 指定的新的可执行程序中的代码。新进程的 PID、 PPID 与原进程完全一样。 并且, exec 一般是不会返回的,因为原进程已经被完全
替换掉了,除非发生错误,出错时, exec 返回-1。
#include <unistd.h>
int execl(const char *path, const char *arg, ..., (char*)0);
int execlp(const char *file, const char *arg, ..., (char*)0);
int execle(const char *path, const char *arg, ..., (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 *file, char *const argv[], char *const envp[]);
6 个函数中只有 execve 是真正意义上的系统调用(内核提供的接口),其他函数都是在此基础上经过封装的库函数。

记忆方法:
 l(list):参数地址列表,以空指针结尾。
 v(vector):存有各参数地址的指针数组地址,使用时先构造一个指针数组,指针数组
存各参数的地址,然后奖该指针数组作为函数的参数。
 p(path):按系统环境变量 PATH 指定的目录去搜索可执行文件。文件名由第一个参数
file 指定,当指定的文件名中包含/,则将其视为路径名,并直接到指定的路径中执行
程序。
 e(environment):存有环境变量字符串地址的指针数组首地址。 execle 和 execve 改
变的是 exec 启动的程序的环境变量(新的环境变量完全由 environment 指定)。其他
四个函数启动的程序则使用默认系统环境变量。
可能的调用形式:
char *const ps_argv[] = {"ps", "ax", 0};
char *const ps_envp[] = {"PATH=/bin:/usr/bin", 0};
execl("/bin/ps", "ps", "ax", 0);
execlp("ps", "ps", "ax", 0);
execle("/bin/ps", "ps", "ax", 0, ps_envp);
execv("/bin/ps", ps_argv);
execvp("ps", ps_argv);
execve("/bin/ps", ps_argv, ps_envp);


示例: execlp.c
#include "common.h"
int main(void)
{
printf("Running ps with execlp\n");
execlp("ps", "ps", 0); /*此处用ps替换当前进程,后面的Done不会打印*/
printf("Done.\n");
return 0;
}


进程的复制
要在程序中创建一个完全分离的进程,还可以使用复制进程的方式,使用 fork 系统调用来完成。 fork 系统调用复制当前进程,在进程表中创建一个新的表项,新表项中许多属性与当前进程是相同的。新进程几乎与原进程一模一样,执行的代码也完全相同,但新进程有自己的数据空间、环境和文件描述符。 fork和exec 系列函数结合在一起使用就是创建新进程所需要的一切了。
头文件:
#include <sys/types.h>
#include<unistd.h>


pid_t fork(void);
功能:
fork()函数用于从一个已存在的进程中创建一个新进程,新进程称为子进程,原进程
称为父进程。 子进程从 fork 之后的代码开始执行。

返回值: 成功: 子进程中返回 0,父进程中返回子进程 ID。
失败:返回-1。

使用 fork 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间。

地址空间:包括进程上下文、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。

tips:子进程所独有的只有它的进程号,计时器等,因些,使用 fork 函数的代价很大。

示例: fork1.c

#include "common.h"
int main(void)
{
pid_t pid;
pid = fork();
if(pid < 0)
err_sys("fork error");
else if(pid == 0)
{
printf("child process\n");
printf("child pid:%d\n", getpid());
printf("child ppid:%d\n", getppid());
}
else
{
printf("parent process\n");
printf("parent pid:%d\n", getpid());
}
return 0;
}
程序在调用 fork 时被分为两个独立的进程,程序通过 fork 调用的返回值判断父子进程。

 

转载于:https://www.cnblogs.com/kylin923/p/6474511.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值