exec()函数原型如下
int execl(cons char *pathname, const char *arg0,....);
int execle(const char *pathname, const char *arg0,..../*char *const envp[]*/);
int execv(const char *pathname,char *const argv[];
int execve(const char *pathname,char *const argv[],char *const envp[]);
int execlp(const char *filename,const char *arro,...);
int execvp(const char *filename, char *const argv[]);"l"表示list,说明执行程序的命令行参数以列表的方式提供,并且以NULL结尾,但是没有参数个数限制。
"v"表示vector,说明命令行参数要以二维数组的形式提供给新程序,这个数组的每一行是一个命令参数。
"e"表示传递给新程序的环境变量,这个列表是一个二维数组,每一行是一个环境变量。如果没有显示地传递一个环境
表量表,那么新程序将复制父进程的环境表。
以p结尾的exec()函数表示第一个参数不是完整的路径名,而是一个程序名。
返回值:如果成功不返回任何值,如失败则返回-1。
例:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
int main(void)
{
pid_t pid;
pid = fork();
if(pid<0){
printf("fail to fork\n");
exit(0);
}else if(pid == 0){
if(execvp("./hello",NULL) < 0) {
printf("fail to exec\n");
printf("%s\n",strerror(errno));
exit(errno);
}
printf("the child is not hello\n");
exit(errno);
}
printf("the parent\n");
return 0;
}
$ls
hell.c hello hello.c test test.c
$./test
the parent
hello
执行了exec()函数的进程不改变以下进程特征
1、进程ID和父进程ID
2、实际用户ID和实际组ID
3、进程组ID和附加组ID
4、控制终端
5、会话ID
6、时钟余留时间
7、当前工作目录和根目录。
8、文件创建屏蔽字和文件锁
9、信号屏蔽字和未处理信号集
10、资源限制。
改变
1、有效用户ID和有效组ID2、在程序中执行shell命令
system()函数调用shell指令
#include<stdlib.h>int system(const char * cmdstring)
参数cmdstring是需要执行的shell命令。
system的返回值的情况比较复杂,system()函数是一个库函数,其中封装了fork、exec和waitpid这个3个系统,
其返回值也要根据这3个系统调用的情况来讨论
1、如果fork()函数和waitpid函数执行失败,则system()函数返回-1
2、如果exec()函数执行失败,system()函数返回如图shell调用了exit(127)一样,表示指定文件不可执行
3、如果3个函数都成功执行,system()函数返回执行程序的终止状态,其值和echo $?的值是一样的。
4、如果参数cmdstring所指向的命令字符串为NULL,system()函数返回1。
例:#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#define MAX 1024
int main(void)
{
int fd,n;
char buf[MAX];
if(system("ls > temp.txt") == -1) {
perror("fail to exec command\n");
exit(0);
}
if(fd = open("temp.txt",O_RDWR) == -1) {
perror("fail to open\n");
exit(1);
}
if(fd = read(fd,buf,MAX) == -1){
perror("fail to read\n");
exit(1);
}
buf[n] = '\0';
printf("%s",buf);
return 0;
}
$gcc system.c -o system
$./systemtemp.txt
system.c
system3、等待进程退出操作
a、
wait()函数得到子进程的结束信息。
#include<sys/wait.h>
pid_t wait(int *statloc);
调用wait()函数的进程会阻塞,直到该进程的任意一个子进程结束。wait()函数会取得结束的子进程的信息并返回子进程的进程ID,结束信息保存在参数statloc所指向的内存空间中,如果该进程没有子进程,则立即出错返回,返回值为-1.
状态 判断宏 取得宏进程正常结束 WIFEXITED(status) WEXITSTATUS(status)
进程异常结束 WIFSIGNALED(status) WTERMSIG(status)
进程暂停 WIFSTOPPED(status) WSTOPSIG(status)
例:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
pid_t pid;
int num,status;
pid = fork();
if(pid<0){
printf("fail to fork\n");
exit(0);
}else if(pid == 0) {
printf("the fist, exit normally\n");
exit(0);
}else {
if(wait(&status) == -1) {
perror("fail to wait");
exit(1);
}
if(WIFEXITED(status) == 1) {
printf("the status of first is :%d\n",WEXITSTATUS(status));
}
}
pid = fork();
if(pid<0) {
printf("fail to fork\n");
exit(0);
}else if(pid == 0) {
printf("the second, exit abnormally\n");
num = 1/0;
}else {
if(wait(&status) == -1){
perror("fail to wait");
exit(1);
}
if(WIFEXITED(status) == 1) {
printf("the terminated signal is :%d\n",WEXITSTATUS(status));
}
}
return 0;
}
$gcc wait.c -o wait
$./wait
the first ,exot normally
the stasus of first is:0
the second,exit abnormally
the terminated signal is:8
b、#include<sys/wait.h>
pid_t waitpid(pid_t pid, int *statloc,int options);pid :指定要等待的子进程的进程ID,其还有一些其他作用,如
-1 : 等待任意子进程
>0: 等待进程ID和pid相等的子进程
0: 等待组ID和pid相等的子进程
<-1: 等待组ID等于pid绝对值的组内的任意子进程。
option:
WCONTINNUED : 当进程在暂停后继续执行,且其状态尚未报告,则返回其状态
WNOHANG: 当等待进程尚未结束运行时不阻塞,waitpid()函数直接返回
WUNTRACED: 当子进程暂停,并且其状态自暂停以来还未报告过,则返回其状态
例:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
pid_t pid;
int num,status;
pid = fork();
if(pid<0) {
printf("fail to fork\n");
exit(1);
}else if(pid == 0) {
printf("the to fork\n");
sleep(5);
exit(0);
}else {
printf("the parent\n");
if(waitpid(pid,NULL,WNOHANG) == 0) {
printf("the child is not available now\n");
}
}
printf("no waiting,parent done\n");
return 0;
}
$gcc waitpid.c -o waitpid./waitpid
the parent
the child is not available nowno waiting, parent done
the child
waitpid()函数和wait()函数的区别有以下3点:
1、waitpid()函数可以指定一个子进程。
2、waitpid()函数可以不阻塞等待一个子进程。
3、waitpid()函数支持作业控制。4、输出进程统计信息
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/time.h>
#include<sys/source.h>
pid_t wait3(int *statlic, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options,struct rusage *rusage);