文章目录
一、函数原型
注:
以上6个接口都是UNIX C接口,不过只有execve是系统调用接口,其它5个实现都需要间接调用execve
二、函数区别
标志:
-
p
可执行文件名作为参数(无须指定路径) -
l/v
l和v标志互斥,l表示通过可变长char * 指针;v表示通过指针数组 -
e
使用envp表示的环境变量覆盖子进程环境变量
三、示例代码
execl
程序设计:
父进程 不停的休息(休息中可能被信号打断),并负责回收子进程资源,结束状态
子进程 打印一行Hello World!
子进程
#include <iostream>
using namespace std;
void print_arg(int argc, char * argv[])
{
for(int cnt = 0; cnt < argc;cnt++)
{
cout << "argv[" << cnt << "]: " << argv[cnt] << endl;
}
}
int main(int argc, char *argv[])
{
print_arg(argc,argv);
cout << "Hello World!" << endl;
return 0;
}
父进程
#include <iostream>
using namespace std;
extern "C"
{
/*pid_t wait(int *status);*/
#include <sys/types.h>
#include <sys/wait.h>
/*fork sleep*/
#include <unistd.h>
/*signal*/
#include <signal.h>
}
void signal_child(int signum)
{
int status = 0;
pid_t pid = wait(&status);
if(-1 == pid)
{
cout << "No child process" << endl;
}
else
{
cout << "waited child process pid = " << pid << endl;
if(WIFEXITED(status))
{
cout << "exited status = " << WEXITSTATUS(status) << endl;
}
else
{
cout << "aborted status = " << WTERMSIG(status) << endl;
}
}
}
int main(void)
{
int res = 0;
pid_t pid = 0;
/*sigchld*/
if(SIG_ERR == signal(SIGCHLD,signal_child))
{
cout << "Error signal CHLD regester" << endl;
}
pid = fork();
if(-1 == pid)
{
res = -1;
goto End;
}
if(0 == pid)
{
/*child process*/ /*Just print为子进程argv[0] */
execl("/home/jianleya/HelloWorld","Just print",NULL);
}
else
{
/*father process*/
while(1)
{
sleep(5);
cout << "Snap 5 secs" << endl;
}
}
End:
return res;
return 0;
}
execlp(相比execl,更简洁)
if(0 == pid)
{
/*child process,相比execl,只需要改动这里即可*/
execl("HelloWorld","Just print",NULL);
}
else
{
/*father process*/
while(1)
{
sleep(5);
cout << "Snap 5 secs" << endl;
}
}
execle(修改环境变量)
父进程
#include <iostream>
using namespace std;
extern "C"
{
/*pid_t wait(int *status);*/
#include <sys/types.h>
#include <sys/wait.h>
/*fork sleep*/
#include <unistd.h>
/*signal*/
#include <signal.h>
}
void signal_child(int signum)
{
int status = 0;
pid_t pid = wait(&status);
if(-1 == pid)
{
cout << "No child process" << endl;
}
else
{
cout << "waited child process pid = " << pid << endl;
if(WIFEXITED(status))
{
cout << "exited status = " << WEXITSTATUS(status) << endl;
}
else
{
cout << "aborted status = " << WTERMSIG(status) << endl;
}
}
}
int main(void)
{
int res = 0;
pid_t pid = 0;
/*sigchld*/
if(SIG_ERR == signal(SIGCHLD,signal_child))
{
cout << "Error signal CHLD regester" << endl;
}
/*子进程 新的环境表*/
char* pv[] = {"PATH=.","Author=yanjianlei",NULL};
pid = fork();
if(-1 == pid)
{
res = -1;
goto End;
}
if(0 == pid)
{
/*child process*/
execle("HelloWorld","Just print",NULL,pv);
}
else
{
/*father process*/
while(1)
{
sleep(5);
cout << "Snap 5 secs" << endl;
}
}
End:
return res;
return 0;
}
子进程
#include <iostream>
#include <cstdio>
using namespace std;
extern "C"
{
extern char **environ;
}
int my_printenv(void)
{
char *pstr = NULL;
if(environ == NULL)
return -1;
else
{
for(pstr=*environ;(pstr!=NULL);environ++)
{
pstr= *environ;
cout << pstr << endl;
}
}
}
void print_arg(int argc, char * argv[])
{
for(int cnt = 0; cnt < argc;cnt++)
{
cout << "argv[" << cnt << "]: " << argv[cnt] << endl;
}
}
int main(int argc, char *argv[])
{
my_printenv();
print_arg(argc,argv);
cout << "Hello World!" << endl;
return 0;
}
execv(对比execl)
#include <iostream>
using namespace std;
extern "C"
{
/*pid_t wait(int *status);*/
#include <sys/types.h>
#include <sys/wait.h>
/*fork sleep*/
#include <unistd.h>
/*signal*/
#include <signal.h>
}
void signal_child(int signum)
{
int status = 0;
pid_t pid = wait(&status);
if(-1 == pid)
{
cout << "No child process" << endl;
}
else
{
cout << "waited child process pid = " << pid << endl;
if(WIFEXITED(status))
{
cout << "exited status = " << WEXITSTATUS(status) << endl;
}
else
{
cout << "aborted status = " << WTERMSIG(status) << endl;
}
}
}
int main(void)
{
int res = 0;
pid_t pid = 0;
/*sigchld*/
if(SIG_ERR == signal(SIGCHLD,signal_child))
{
cout << "Error signal CHLD regester" << endl;
}
/*env child*/
//char* pv[] = {"PATH=.","Author=yanjianlei",NULL};
/*argv child*/
char *argv[] = {"Just print","Learn and Enjoy",NULL};
pid = fork();
if(-1 == pid)
{
res = -1;
goto End;
}
if(0 == pid)
{
/*child process*/
execv("/home/jianleya/HelloWorld",argv);
}
else
{
/*father process*/
while(1)
{
sleep(5);
cout << "Snap 5 secs" << endl;
}
}
End:
return res;
return 0;
}
execvp(对比execlp)
略
execvpe(对比execle)
略
四、文件资源
execve 系统调用 文件管理:
目录->子进程所有打开的目录都需要关闭
文件->根据close on exec 标志,决定是否关闭文件
一般来说:
操作系统会自动把原来子进程指向的共享库文件和可执行文件关闭,并打开一个新的可执行文件
五、system
1、函数原形
#include <stdlib.h>
int system(const char *command);
2、实现原理
system通过调用fork,execl,waitpid实现;父进程会阻塞等待子进程退出
execl("/bin/sh", “sh”, “-c”, command, (char *) 0);
3、示例代码
#include <iostream>
using namespace std;
#include <cstdlib>
int main(void)
{
system("date > file");
return 0;
}