Linux中的exec函数族一共有6个函数:
#include <unistd.h>
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 execve(const char *path, char *const argv[], char *const envp[])
其中execve函数是真正意义上的系统调用,其他的都是在其基础上的经包装之后的库函数。
下面重点讲解一下execve函数,函数的原型为:
int execve(const char *filename,char const* argv[] , char *const envp[]) ;
在讲解execve之前,让我们再来看看一个“另类”的main函数,平时写程序的时候,我们总是将main函数写成这样:
int main(int argc, char *argv[]) ;
但是真正完整的main函数应该是:
int main(int argc, char *argv[] ,char *envp[])
其中: argc是我们所熟悉的命令行输入的参数个数
argv中存放的是命令行输入的参数的内容,一个二维的数组。
envp是新增加的一个参数,其存放的是该程序运行的环境变量,所谓的环境变量就是一组制定OS运行环境的变量。
好了,介绍完了这个main函数之后, 让我们再回到execve上,对比这两者参数的区别,很明显就可以看出,两者只有第一个参数不一样,execve的第一个参数是filename,而main函数的第一个参数是argc。下面就介绍一下execve中各参数表示的意思。
int execve(const char *filename, char *const argv[], char *const envp[])
filename:指定二进制可执行文件或是文件开头包含#!的脚本文件的路径(名称)。
argv:存放传递给filename文件的参数,以NULL结束,但是第一个元素是命令自己(即第一个参数的值和filename相同)。
envp:存放程序运行的环境变量。
介绍完了函数的各参数之后,下面给出execve函数的两个应用,一个filename是一个可执行文件,另外一个是一个脚本。
filename是脚本文件。
/*
execve 函数的应用实例
execve(const char *filename , char *argv[] , char *envp[])
*/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
int main( int argc, char *argv[] ,char *envp[] ){
pid_t pid ;
pid = fork() ;
if(pid < 0)
{
fprintf(stderr,"ERROR!\n");
exit(-1) ;
}
else if(pid == 0){
printf("This is Child process!\n");
char *arg[] = {"binary.sh","100010101",NULL} ;
execve("binary.sh",arg,envp);
exit(0) ;
}
else{
printf("This is Parent Process!\n");
waitpid(pid,NULL,0);
exit(0) ;
}
return 0;
}
binary.sh的源代码为:
#!/bin/bash
#将一个二进制转换为十进制的脚本
# help function
function my_help()
{
cat<<HELP
THis is a script to change the binary number to decimal number
USAGE : binary.sh [-h] 100101
Resualt : 37
HELP
exit 0
}
# check whether input the "-h"
while [ -n "$1" ] ;do
case "$1" in
-h) my_help ; shift ;;
*) break ;;
esac
done
#get the last char in $var
function lastchar()
{
if [ -z "$1" ] ;then
# the string is empty .
num=""
return
fi
# calculate the length of string
numbit=`echo -n $1 | wc -c | sed 's/ //g'`
# get the last char
num=`echo -n $1 | cut -b $numbit`
}
# delete the last char of $var
function chop()
{
var1=$var
if [ -z "$var1" ];then
# empty string
var=""
return
fi
# calculate the length of the string .
numbit=`echo -n "$var1" | wc -c | sed 's/ //g'`
if [ "$numbit" = "1" ]; then
# Only 1 char in string .
var=""
return
fi
# length minus 1
let numbit=numbit-1
# cut a new var
var=`echo -n "$var1" | cut -b 1-$numbit`
}
# answer of the decimal
sun=0
weight=1
var="$1"
var_orig="$1"
[ -z "$1" ] && my_help
# main program
while [ -n "$var" ]; do
# get the last number of $var
lastchar "$var"
if [ "$num" == "1" ];then
# the last number is 1 ,then plus the weight
let sun+=weight
fi
let weight*=2
# delete the last char in $var
chop "$var"
done
echo "$var_orig" is changed to decimal is "$sun"
filename为二进制可执行文件:
/*
execve 函数的应用实例
execve(const char *filename , char *argv[] , char *envp[])
*/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
int main( int argc, char *argv[] ,char *envp[] ){
pid_t pid ;
pid = fork() ;
if(pid < 0)
{
fprintf(stderr,"ERROR!\n");
exit(-1) ;
}
else if(pid == 0){
printf("This is Child process!\n");
char *arg[] = {"test","I","am","chris",NULL};
execve("test",arg,envp);
exit(0) ;
}
else{
printf("This is Parent Process!\n");
waitpid(pid,NULL,0);
exit(0) ;
}
return 0;
}