在进程中运行新代码
execX系列函数可以在当前子进程中运行新程序。当进程调用该系列任意一个函数时,该进程的用户空间资源完全由新程序替代。
这些函数的区别:指示新程序的位置是使用路径还是文件名,若是文件名则在系统的$PATH环境变量所描述的路径中搜索该程序。
在使用参数时,是使用参数列表的方式还是使用argv[]数组的方式
函数 | 使用文件名 | 使用路径名 | 使用参数表(函数出现字母l) | 使用argv(函数出现字母v) |
execl | √ | √ | ||
execlp | √ | √ | ||
execle | √ | √ | ||
execv | √ | √ | ||
execvp | √ | √ | ||
execve | √ | √ |
int execl (__const char *__path, __const char * __arg, ...): 执行path字符串所指向的程序,后面的参数是参数列表。最后必须传入空指针。
#include<unistd.h> #include<stdio.h> #include<sys/types.h> int main(int argc, char *argv[]) { pid_t pid; if((pid = fork()) < 0) printf("error "); else if(pid == 0) { execl("/bin/ls","ls","-l","/home",(char *)0); //子进程执行新函数 } else printf("father ok! "); return 0; }
int execle (__const char * __path, __const char *__arg, ...):最后一个参数必须指向一个新的环境变量数组,即新执行程序的环境变量。
#include<unistd.h> int main(int argc, char *argv[], char *env[]) { execl("/bin/ls","ls","-l","/home",(char *)0,env); //子进程执行新函数 return 0; }
int execlp(__const char * __file, __const char * __arg, ...):在$PATH环境变量中查找文件并执行,最后一个参数必须用空指针NULL
#include<unistd.h> int main(int argc, char *argv[], char *env[]) { execlp("ls","ls","-l","/home",(char *)0); //子进程执行新函数 return 0; }
int execv (__const char * __path, char * __const __argv[]):第二个参数是数组指针维护的程序参数列表。数组的最后一个成员必须为NULL。
#include<unistd.h> int main() { char * argv[] = {"ls","-l","/home",(char *)0}; execv("/bin/ls", argv); //子进程执行新函数 return 0; }
int execvp (__const char * file, char * __const __argv[]):使用文件名,第二的参数的最后一个成员必须是NULL。
#include<unistd.h> int main() { char * argv[] = {"ls","-l","/home",(char *)0}; execvp("ls", argv); //子进程执行新函数 return 0; }
int system (__const char * __command):创建新进程,并运行,直到新进程运行结束后,才继续运行父进程。
#include<stdlib.h> #include<sys/wait.h> #include<stdio.h> int main(int argc, char *argv[]) { int status; status = system("pwd"); if(!WIFEXITED(status)) printf("abnormal exit "); else printf("the exit status is %d ", status); return 0; }
执行新代码,对打开文件的处理
原来的文件描述符可以使用,但如果使用了fcntl(fd, F_SETFD, FD_CLOEXEC)即关闭FD_CLOEXEC项,则在执行execX系列函数后关闭原来打开的文件描述符。
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<string.h> #include<stdlib.h> int main(int argc, char * argv[]) { int fd, status; pid_t pid; fd = open("test.txt", O_RDWR|O_APPEND|O_CREAT,0644); if(fd == -1) { perror("open"); exit(EXIT_FAILURE); } //fcntl(fd, F_SETFD,FD_CLOEXEC); //如果执行此句,将导致错误 printf("before child process write "); system("cat test.txt"); //查看执行newcode前内容 if((pid=fork()) == -1) { perror("fork"); exit(EXIT_FAILURE); } if(pid == 0) //子进程 { char buf[128]; sprintf(buf, "%d", fd); execl("./newcode","newcode",buf,(char *)0); } else { wait(&status); printf("after child_process write "); system("cat test.txt"); //查看内容是否有效 } }
#include<stdio.h> #include<unistd.h> #include<string.h> int main(int argc, char * argv[]) { int i; int fd; char *ptr = "helloworld "; fd = atoi(argv[1]); i = write(fd,ptr,strlen(ptr)); if(i<=0) perror("write"); close(fd); }
可见,新代码中可以使用原来的文件描述符。