exec族函数:
exec族函数的作用:
(1)一个父进程希望复制自己,使父子进程同时执行不同的代码段,如父进程等待客户端的服务请求。当这种请求到达时,父进程嗲用fork(),使子进程处理次请求,父进程则继续等待下一个服务请求到达。
(2)一个进程要执行一个不同的程序。在这种情况下,子进程fork返回后立即调用exec。
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
execl:
int execl(const char *path, const char *arg, …);
第一个参数是所需要执行文件或指令的路径,第二个参数是文件名或者指令,第三个参数为调用该文件所需要的参数,每个参数以逗号隔开,最后还需要一个NULL作为execl的结尾。
#include
#include
#include
//int execl(const char *path, const char *arg, ...);
int main()
{
int ret = execl("/bin/ls","ls",NULL);//第一个参数为ls的默认路径,使用whereis ls查看文件位置,第二个参数为该文件名,如果使用ls -l指令,就需要在第三个指令处输入"-l"(注意是以指针的形式),并且整个execl函数需要一个NULL进行结尾。
if(ret == -1){
printf("execl failed\n");
perror("why"); //使用失败可以用perror()解析失败原因
}
return 0;
}
execlp
int execlp(const char *file, const char *arg, …);该指令不需要输入执行文件或者命令的路径,第一个参数无需给出具体的路径,只需给出函数名即可,系统会在PATH环境变量中寻找所对应的程序,如果没找到的话返回-1。
#include
#include
#include
//int execlp(const char *file, const char *arg, ...);
int main()
{
int ret = execlp("ls","ls","-l",NULL);
if(ret == -1){
printf("execlp failed\n");
perror("why");
}else{
printf("execlp suxxess\n");
}
return 0;
}
执行结果:
execv和execvp只是将execl中的参数定义为一个字符串
#include
#include
#include
//int execl(const char *path, const char *arg, ...);
int main()
{
char *argv[] = {"ls",NULL}; //将execl中的第二位之后的参数定义为字符串放入execl
int ret = execv("/bin/ls",argv);
if(ret == -1){
printf("execl failed\n");
perror("why");
}else{
printf("execl suxxess\n");
}
return 0;
}
执行结果:
execl与进程的综合应用:
在子进程使用execl执行文件修改配置文件:
配置文件:
test.config
SPEED = 3
CAO = 9
HAI = 1
JAING = 5
修改文件:
change.c
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
char *readBuf = NULL;
int fd = open(argv[1],O_RDWR|O_CREAT,0600);
if(fd == -1){
printf("file open failed\n");
}
int cnt = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
readBuf= (char*)malloc(cnt*sizeof(char));
int ret_READ = read(fd,readBuf,cnt);
char *p = strstr(readBuf,"CAO = ");
*(p + strlen("CAO = ")) = '2';
lseek(fd,0,SEEK_SET);
int ret_WRITE = write(fd,readBuf,cnt);
close(fd);
return 0;
}
创建进程文件:
exc.c
include <unistd.h>
#include
#include
int main()
{
pid_t pid;
int data;
while(1){
printf("please input data\n");
scanf("%d",&data);
if(data == 1){
pid = fork();
if(pid > 0){
printf("this is father pid\n");
}else if(pid == 0){
execl("./change","change","test.config",NULL);
}
}
}
return 0;
}
执行后配置文件内容被修改:
SPEED = 3
CAO = 2
HAI = 1
JAING = 5
system函数:
使用system函数结束后,原程序依然能够执行之后的代码,而exec族函数执行完之后程序就飞掉,无法执行函数之后的代码。
int system(const char *command);
如果system()在调用/bin/sh时失败则返回127,其他原因返回-1。若参数为空指针则返回非零值
将exec族函数改用system
include <unistd.h>
#include
#include
int main()
{
pid_t pid;
int data;
while(1){
printf("please input data\n");
scanf("%d",&data);
if(data == 1){
pid = fork();
if(pid > 0){
printf("this is father pid\n");
}else if(pid == 0){
system("./change test.config");
}
}
}
return 0;
}
popen函数:
FILE *popen(const char *command, const char *type);
popen函数需要fread去读取文件执行之后的内容,可以将内容放置于字符串中,只有加上打印字符串的命令,执行结果才能打印在shell里。
popen需要使用pclose对其进行关闭。
#include
#include
#include
// FILE *popen(const char *command, const char *type);
//int pclose(FILE *stream);
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
int main()
{
FILE *fp;
char ret[1024] = {0};
fp = popen("ls","r");
int nread = fread(ret,sizeof(char),1024,fp);
printf("read %d byte from fp,contex is %s",nread,ret);
return 0;
}
#include
#include
#include
// FILE *popen(const char *command, const char *type);
//int pclose(FILE *stream);
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
int main()
{
FILE *fp;
char ret[1024] = {0};
fp = popen("ls","r");
int nread = fread(ret,sizeof(char),1024,fp);
// printf("read %d byte from fp,contex is %s",nread,ret);
return 0;
}