进程(五)

创建子进程一,在子进程中递归打印/home目录中的内容(用exec系列函数调用第一次实验中的代码完成此功能);
子进程结束的时候完成以下功能:
打印字符串“Child process exited!”
打印子进程标识符,打印父进程标识符。
创建子进程二, 打印子进程运行环境中环境变量“USER”的值,通过exec系列中的某个函数设置子进程”USER”环境变量值为“zhangsan”,并且让该子进程完成以下命令:“ls-li /home”.

在程序编写之前,我们应该对exec族函数的功能进行一定的了解。

exec族函数的作用是在进程中,通过文件名找到可执行文件(二进制文件或脚本文件)并对其进行调用。一个进程一旦调用exec族的函数,它本身就已经结束了。系统会将原来进程的代码段更新,并废弃其数据段和堆栈段。唯一没有被改变的就是该进程的pid,因此,对于操作系统来说,进程并没有结束,只是更换了新的程序。

于此同时,我们要清楚如何在进程结束时将字符串打印。利用atexit登记函数,可以实现题目要求。

atexit的作用是程序可以在进程结束时完成对进程资源的清理工作,通过登记自定义函数来实现清理工作。注意:先登记的后执行,即登记顺序和执行顺序是相反的。同时,_exit的调用不能触发atexit登记的函数。

atexit函数实例如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void test1(void )
{
	printf("This is the test1!\n");
}

void test2(void)
{
	printf("This is the test2!\n");
}

int main()
{
	if(fork() == 0)
	{
		printf("This is the child!\n");
		atexit(test2);
		atexit(test1);
		exit(1);
	}
	else
	{
		printf("This is father!\n");
	}
	return 0;
}

程序运行结果如下:

通过程序运行结果我们发现,函数的执行顺序确实是和登记顺序相反的。

要想让子进程二执行“ls -li /home”,则可以利用system函数执行。

程序如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void fun(void)
{
	printf("~~~~~~~~~~~~~~~~~~~~~~\n");
	printf("Child process exited!!!\n");
	printf("The child's pid is: %d\n",getpid());
	printf("The father's pid is %d\n",getppid());
	printf("~~~~~~~~~~~~~~~~~~~~~~\n");
}
		
int main()
{
	pid_t pid;
	pid = vfork();

	if(pid <0)
	  perror("vfork");
	else if(pid == 0)
	{
		printf("This is the child1 !!!\n");
		atexit(fun);

		if((execl("/home/wang/test/file/test6/test","test",NULL)) < 0)
		{
		  perror("execl");
		  exit(0);
		}
	}
	else
	{
		printf("This is the father !!!\n");
		if(vfork() == 0)
		{
			printf("This is the child2 !!!\n");
			printf("The child2's father's pid is: %d\n",getppid());
			char * env[] = {"USER=zhangsan",NULL};
			char *p;
			
			p = getenv("USER");
			if(p)
			{
				printf("The user is: %s\n",p);
			}

			system("ls -li /home");
			if((execle("/bin/env","env",NULL,env)) < 0)
			  perror("execle");
			
			exit(1);
		}
	}
	return 0;
}

在我的Fedora中运行程序发现,只用vfork函数创建的子进程中才能成功调用atexit函数,而fork函数创建的子进程下不能实现对atexit函数的调用,但是在我的ubuntu系统中却能正常运行。

程序运行结果: 

实验完成。

猜你喜欢

转载自blog.csdn.net/Wangguang_/article/details/84845490