执行一个新程序 fork + exec
exec
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
int execle(const char *path, const char *arg0, ... /*,(char *)0, char *const envp[]*/);
int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
int execv(const char *path, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
进程的 image = 进程的组成部分(text|data|bss|堆栈)
int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
int execv(const char *path, char *const argv[]);
功能:
执行一个新的程序
l 和 v
list //列举 --- 后面的参数逐个列举出来
vector //向量 --- 后面的参数 以字符串指针数组的形式组织
参数:
@path //说明 --要执行的可执行文件的名字 (包含路径)
@arg0 //执行文件的名字
... //可变参数
//看要执行的文件 是否有需要的参数
//形式 字符串形式 最终 以 NULL作为结尾
ls -l /
execl("/bin/ls","ls","-l","/",NULL);
char *const arg[] = {"ls","-l","/",NULL};
execv("/bin/ls",arg);
bash
|
fork()
/ \
bash bash (+exec 函数调用 --- 它会用新程序的镜像替换原有镜像,
名字也变了,父子关系没变)
int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
int execvp(const char *file, char *const argv[]);
p 表示 要执行的文件 到系统的环境变量PATH中区寻找
ls -l /
execl("/bin/ls","ls","-l","/",NULL);
execlp("ls", "ls","-l","/",NULL);
char *const arg[] = {"ls","-l","/",NULL};
execvp("ls",arg);
int execle(const char *path, const char *arg0, ... /*,(char *)0, char *const envp[]*/);
int execve(const char *path, char *const argv[], char *const envp[]);
e --- environment
应用:
有些程序 ,运行时,需要获得环境变量 (系统的 或者 自定义)
#include<stdio.h>
#include<unistd.h>
extern char **environ;
int main(int argc, const char *argv[])
{
char * const envp[] = {"USER=linux","PSWD=12345",NULL};
//execle("./myenv","myenv",NULL,environ);
//execle("./myenv","myenv",NULL,envp);
char * const arg[] = {"myenv",NULL};
execve("./myenv",arg,envp);
return 0;
}
strtok()
char *strtok(char *str, const char *delim);
功能:
分割字符串
参数:
str 表示要分割的字符串 //如果填写NULL 表示接着原来的字符串继续分割
delim 表示分割标志
返回值:
成功 返回分割出来的字符串地址
失败 返回NULL
char *arg[] = {"ls","-l","/",NULL};
execvp(arg[0],arg);
#include<stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{
char buf[] = "ls;-l;/:";
int len = strlen(buf);
char *arg[20] = {NULL};
arg[0] = strtok(buf,";:");
int i = 0;
while(arg[++i] = strtok(NULL,";:"));
for(i=0;i<10;++i)
{
printf("arg[%d] = %s\n",i,arg[i]);
// printf("%s",arg[]);
}
return 0;
}
wait()
pid_t wait(int *wstatus);
功能:
等待子进程状态改变
(主要用来 --- 回收子进程的资源----避免僵尸态)
参数:
wstatus NULL //表示不关心子进程退出时 状态信息
不是NULL //想关心子进程退出状态信息
返回值:
成功 返回结束了的子进程的pid号
失败 -1
说明:
1.wait ---阻塞操作
2.如果没有任何子进程,wait调用失败 --提示 NO child process
3.子进程退出时,
对应的退出状态值,需要使用相关的宏来获取
WIFEXITED //判断是否正常结束
WEXITSTATUS //获取对应的退出状态值
WIFSIGNALED //判断是否被信号结束
WTERMSIG //获得信号的编号
#include<stdio.h>
int main(int argc, const char *argv[])
{
if (pid < 0)
{
perror("fork fail");
return -1;
}
if (pid>0)
{
while(1)
{
printf("father%d\n",getpid());
if(wait(NULL)<0)
{
perror("wait fail");
}
sleep(1);
}
}else if(pid == 0)
{
}
return 0;
}
wait()放在函数内。
//waitpid
pid_t waitpid(pid_t pid, int *wstatus, int options);
The value of pid can be:
< -1 meaning wait for any child process whose process group ID is equal to the absolute value of pid.
eg:
pid = -100
进程组 id = |-100| = 100
-1 meaning wait for any child process.
eg:
pid = -1
等待所有子进程 ---当前进程的所有进程
0 meaning wait for any child process whose process group ID is equal to that of the calling process.
eg:
等待 进程组id = PPID 的进程组中的所有子进程
> 0 meaning wait for the child whose process ID is equal to the value of pid.
eg:
pid = 100
等待 pid 为100的子进程状态改变
options:
WNOHANG 以非阻塞的方式 回收子进程 ---1. 如果是非阻塞 ,在没有子进程状态改变时,此时返回0
2. 必须配合循环使用 (轮询)
0 表示阻塞
waitpid //灵活 + 提供了非阻塞的使用方式