fork()与exec()分析

摘要

UNIX提供了两个系统调用来启动新的进程,分别是fork与exec。其中fork相当于复制其父进程,能够创建一个和当前映像一样的进程。而exec会将二进制程序加载到内存中,替换地址空间原来的内容,并开始执行。

fork

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void)

当fork成功调用后会创建一个与原来进程相同的新进程而原来的进程不会消失。子进程中成功的调用会返回0,父进程中,fork()会返回子进程的pid

  • 子进程的pid是新分配的,与父进程不同。
  • 子进程的ppid会被设置成父进程的pid。
  • 所有挂起的信号以及文件锁都会被清除。

fork系统调用的用法如下:

pid_t pid;

pid = fork();
if (pid>0)
	printf("I am the parent of pid=%d\n",pid);
else if(!pid)
	printf("I am the child!\n");
else if(pid == -1)
	perror("fork");
	

最常见的fork()用法是创建一个新的进程并载入新的二进制映像,下面的例子将创建一个新的进程来运行/bin/windlass:

pid_t pid;

pid = fork();
if (pid==-1)
	perror("fork");
if(!pid){
	const char *args[]={"windlass",NULL};
	int ret;
	
	ret = exev("/bin/windlass",args);
	if(ret == -1){
		perror("execv")
		exit(EXIT_FAILURE)
	}
}
	

除了创建一个新的进程外,父进程将会照常继续运行。调用execv()会使子进程运行/bin/windlass。

exec()

exec()不存在单一的exec函数,而是由一系列的exec函数构成,例如:

#include<unistd.h>

int execl(const char *path,const char *arg,……)

execl会将path所指路径的映像载入内存,替换当前进程的映像,其中argc是其第一个参数,省略号表示可变长度参数列表。

int ret;

ret = execl("/bin/vi","vi","/home/kidd/hooks.txt",NULL);
if (ret == -1)
	perror("execl");

上面的例子中将打开/home/kidd/hooks.txt,通常情况下,execl()不会返回,调用成功后,会跳转到新的程序入口点。

exec调用后进程的其它属性并没有改变,如pid、父进程的pid、优先级以及所属的用户组等

除了execl外,exec系还有其它5个函数,分别为:

#include<unistd.h>

int execlp(const char *file,const char *arg,……);

int execle(const char *path,const char *arg,……, char * const envp[]);

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

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

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

简单记住这些函数的方法是l和v分别表示参数是以列表方式还是数组方式提供的,p表示会在用户的绝对路径path下查找可执行文件。e表示会为新的进程提供新的环境变量。

posted @ 2020-05-28 15:16  _Koln  阅读(348)  评论(0)    收藏  举报