第八节 在进程中执行新程序的三种方法

来源:互联网 发布:大众网络报手游推荐 编辑:程序博客网 时间:2024/06/03 19:11

进程和人类一样,都有产生、生长、睡眠和死亡等各种生命形态。其中,函数fork创建新的进程,函数exec执行新的程序,函数sleep休眠正在执行的进程,函数wait同步进程, exit结束进程,进程就死亡了。

 

(1) fork - exec

调用fork创建的子进程,将共享父进程的代码空间,复制父进程的进程数据空间, 如堆栈等。调用exec函数后,将会使用新程序的代码覆盖进程中原来的程序代码,并使进程使用函数提供的命令行参数和环境变量去执行新的程序。

 

exec函数族有六个函数如下:

 

#include <unistd.h>

int execl(const char *path, const char *arg0, ..., (char *)0);

int execle(const char *path, const char *arg0, ..., (char *)0, char *const envp[]);

int execlp(const char *file, const char *arg0, ..., (char *)0);

int execv(const char *path, const char *argv[]);

int execve(const char *path, const char *argv[], const char *envp[]);

int execvp(const char *file, const char *argv[]);

extern char **environ;

 

如何用fork-exec方式执行程序'uname -a?

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

int main()

{

pid_t pid;

if((pid = fork()) == 0){

fprintf(stderr, "---- begin ----/n");

// sleep(3); // 睡眠3秒会导致子进程成为僵死进程

execl("/bin/uname", "uname", "-a", 0);

fprintf(stderr, "---- end ----/n");

}

else if(pid > 0)

fprintf(stderr, "fork child pid = [%d]/n", pid);

else

fprintf(stderr, "Fork failed./n");

return 0;

}

[bill@billstone Unix_study]$ gcc exec1 -o exec1

[bill@billstone Unix_study]$ ./exec1

---- begin ----

Linux billstone 2.4.20-8 #1 Thu Mar 13 17:18:24 EST 2003 i686 athlon i386 GNU/Linux

fork child pid = [13276]

[bill@billstone Unix_study]$ ./exec1

---- begin ----

fork child pid = [13278]

[bill@billstone Unix_study]$ Linux billstone 2.4.20-8 #1 Thu Mar 13 17:18:24 EST 2003 i686 athlon i386 GNU/Linux

 

(2) vfork-exec

vork比起fork函数更快,二者的区别如下:

(a) vfork创建的子进程并不复制父进程的数据,在随后的exec调用中系统会复制新程序的数据到内存。

(b) 父进程以vfork方式创建子进程后将被阻塞,直到子进程推出或执行exec调用后才能继续运行。

当进程只用来执行新程序时,vfork-exec模型比fork-exec模型具有更高的效率,这种方法也是shell创建新进程的方式。

 

 

//exec2.c

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

int main()

{

pid_t pid;

if((pid = vfork()) == 0){

fprintf(stderr, "---- begin ----/n");

sleep(3);

execl("/bin/uname", "uname", "-a", 0);

fprintf(stderr, "---- end ----/n");

}

else if(pid > 0)

fprintf(stderr, "fork child pid = [%d]/n", pid);

else

fprintf(stderr, "Fork failed./n");

return 0;

}

[bill@billstone Unix_study]$ gcc exec2.c -o exec2

[bill@billstone Unix_study]$ ./exec2

---- begin ----

fork child pid = [13293]

[bill@billstone Unix_study]$ Linux billstone 2.4.20-8 #1 Thu Mar 13 17:18:24 EST 2003 i686 athlon i386 GNU/Linux

 

(3) system

在UNIX中,我们也可以使用system函数完成心程序的执行。

nt system(const char * string);  函数说明  system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。  返回值  =-1:出现错误  =0:调用成功但是没有出现子进程  >0:成功退出的子进程的id  如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值>。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。  附加说明  在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。

 

//exec3.c

#include <unistd.h>

#include <stdio.h>

int main()

{

char cmd[] = {"/bin/uname -a"};

system(cmd);

return 0;

}

[bill@billstone Unix_study]$ gcc exec3.c  -o exec3

[bill@billstone Unix_study]$ ./exec3

Linux billstone 2.4.20-8 #1 Thu Mar 13 17:18:24 EST 2003 i686 athlon i386 GNU/Linux

[bill@billstone Unix_study]$

 

 

原创粉丝点击