系统调用的常用方法:
一.系统调用方法用来运行不同的程序,格式为:
int execve(const char* filename, char* const argv[], char* const envp[]);
该方法以argv
为参运行filename
指向的可执行程序,并将envp
存储的“变量=数值”对作为环境变量代入这个程序。argv
的第一个参数必须与filename
一致,真正的参数从第二个开始。
注意!!
该方法会让filename
的程序覆盖进程中正在运行的程序,因此该方法后的代码无法被执行(除非该方法运行失败)
二.在 Linux 系统中,比起系统调用更常使用以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[]);
它们都具有系统调用功能,可将这些函数表示为:“exec + l/v + p/e/pe”,这六个函数主要有两处不同:
第一处不同(l/v)——“l”类函数将所有参数作为一整个字符串代入,而“v”类函数将参数分别放入一个字符串数组中,将数组作参代入函数运行
第二处不同(p/e/pe)——包含 p的函数可以模仿计算机中壳功能,在“file”中不含“/”时使用环境变量 PATH 中的目录来寻找可执行文件,包含 e的函数可以像execve
一样将“变量=数值”对作为环境变量代入程序
三.用法
使用系统调用函数一般先调用fork()产生新进程,然后再新进程中用exec()
类函数运行新程序。
可能大家有疑问,调用fork()会复制了全部父进程地址空间又弃置,会造成浪费。
其实, Linux 系统采用了 copy_on_write 技术,只有在某一数据被修改时那个数据才会被实际复制到子进程的地址空间。所以在fork()
之后直接运行exec()
时,父进程的地址空间不会被复制过来。
举个栗子:
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
int count = 0;
int main(){
int pid = fork();
if (pid==0){
count++;
int pid2 = fork();
if (pid2 == 0){
char** argv = (char**) malloc(3*sizeof(char*));
argv[0] = "echo";
argv[1] = "Hello!";
argv[2] = NULL;
int pid3 = fork();
count++;
if (pid3 == 0){
count++;
execvp("echo", argv);
printf("Count %d,",count);
exit(0);
} else {
free(argv);
wait(NULL);
printf("%d,",count);
exit(0);
}
} else {
wait(NULL);
printf("%d,",count);
exit(0);
}
} else {
wait(NULL);
printf("%d.",count);
return 0;
}
}
最后输出为:hello!
2,1,0.
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢