进程控制2 华清远见-《嵌入式 Linux 应用程序开发标准教程》

fork一次,父亲进程将会复制出一个子进程,而父子进程的代码从fork函数的返回开始分别在来那个个地址空间中同时运行。从而两个进程分别获得其所属的fork()函数的返回值。vfork函数不同于fork函数,vfork函数的作用是应用了当子进程需要改变内存中的数据的时候才复制父进程,这就是著名的“写操作时复制”

<span style="font-size:18px;">#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	pid_t result;

	/*调用fork函数,其返回值为result*/
	result = fork();

	/*通过result的值来判断fork函数的返回情况,首先进行出错处理*/
	if(result ==  -1)
	{
		printf("Fork error\n");
	}
	else if (result == 0) /*返回值为0代表子进程*/
	{
		printf("The return value is %d\nIn child process!!\nMy PID is %d\n",result,getpid());
	}
	else /*返回值大于0代表父进程*/
	{
		printf("The return value is %d\nIn father process!!\nMy PID is %d\n",result,getpid());
	}

	return result;
}</span>

exec函数族的功能就是在一个进程中启动另一个程序执行,它可以根据指定的文件名或者时目录名找到可执行的文件,并用他来取代原来调用进程的  数据段 、代码段、 堆栈段 ,执行之后,原来的进程中的内容除了进程号之外,其他的全部都被新的进程替换了。这里可以执行的文件既可以时二进制的文件、也可以运行可执行脚本。


使用execl使用完整的文件目录来查找对应的可执行文件。必须以“/”开头,否则将其视为文件名

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

int main()
{
	int ret;

	if ((ret = fork()) == 0)
	{
		/*调用execl函数,注意这里要给出ps程序所在的完整路径*/
		if ((ret = execl("/bin/ps","ps","-ef",NULL)) < 0)
		{
			printf("Execl error\n");
		}
	}

	return ret;
}


execlp函数的意义在于使用文件名的方法来查找可执行文件,同时使用参数列表的方式。

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

int main()
{
	int ret;

	if ((ret = fork()) == 0)
	{
		/*调用execlp函数,这里相当于调用了"ps -ef"命令*/
		if ((ret = execlp("ps", "ps", "-ef", NULL)) < 0)
		{
			printf("Execlp error\n");
		}
	}

	return ret;
}


execle,将环境变量添加到新建的子进程中,env查看当前进程环境变量的命令

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

int main()
{
	/*命令参数列表,必须以NULL结尾*/
	char *envp[]={"PATH=/tmp","USER=root", NULL};

	if (fork() == 0)
	{
		/*调用execle函数,注意这里也要指出env的完整路径*/
		if (execle("/usr/bin/env", "env", NULL, envp) < 0)
		{
			printf("Execle error\n");
		}
	}
}
execve函数,通过构造指针数组的方式来传递参数

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

int main()
{
	/*命令参数列表,必须以NULL结尾*/
	char *arg[] = {"env", NULL};
	char *envp[] = {"PATH=/tmp", "USER=david", NULL};

	if (fork() == 0)
	{
		if (execve("/usr/bin/env", arg, envp) < 0)
		{
			printf("Execve error\n");
		}
	}
}
exec函数族很容易失败,需要加入判断语句。可能找不到文件或者路径,此时errno被设置为ENOENT。数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT。没有对应的文件的执行权限,此时errno被设置为EACCES。


进程退出控制函数exit(stdlib.h)和_exit(unistd.h)

都能够是当前运行的进程退出,不同之处为exit()可以保证数据的完整性,可以处理IO数据缓存区,将IO缓存区的内容可以安全的写回文件,然后在退出。参数0表示正常退出,非零则为异常退出。

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

int main()
{
  	  printf("Using exit...\n");
  	  printf("This is the content in buffer");
  	  exit(0);
}
Using exit...
This is the content in buffer

exit执行之后,该进程不会立刻消失,而是会留下一个“僵尸进程”的数据结构,这个“僵尸进程”已经放弃了几乎所有的内存空间,没有任何可执行的代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其它进程收集,他不会占用任何的内存空间。

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

int main()
{
  	  printf("Using _exit...\n");
  	  printf("This is the content in buffer");
  	  _exit(0);
}
Using _exit...  没有输出下方的提示


wait:用于使父进程阻塞,直到一个子进程结束或者该进程接到一个指定的信号为止,如果父进程没有子进程或者子进程已经结束,则wait就会立即返回。

waitpid:和wait作用一样,但是它并不一定要等待第一个终止的子进程,它还有若干选项,如果可以提供一个非柱塞版本的wait,也支持作业控制,实际上wait函数只是waitpid函数的一个特例。

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
	pid_t pc, pr;

	pc = fork();
	if (pc < 0)
	{
		printf("Error fork\n");
	}
	else if (pc == 0) /*子进程*/
	{
		/*子进程暂停5s*/
		sleep(5);

		/*子进程正常退出*/
		exit(0);
	}
	else /*父进程*/
	{
		/*循环测试子进程是否退出*/
		do
		{
			/*调用waitpid,且父进程不阻塞*/
			pr = waitpid(pc, NULL, WNOHANG);// pc肯定大于零,fork的返回值在父进程中返回的是子进程的PID
			//等待的子进程退出,则会返回子进程的PID

			/*若子进程还未退出,则父进程暂停1s*/
			if (pr == 0)
			{
				printf("The child process has not exited\n");
				sleep(1);
			}
		} while (pr == 0);

		/*若发现子进程退出,打印出相应情况*/
		if (pr == pc)  //fork的返回值在父进程中返回的是子进程的PID
		{
			printf("Get child exit code: %d\n",pr);
		}
		else
		{
			printf("Some error occured.\n");
		}
	}

	return 0;
}
The child process has not exited
The child process has not exited
The child process has not exited
The child process has not exited
The child process has not exited
Get child exit code: 12620

将 pr = waitpid(pc, NULL, WNOHANG);// pc肯定大于零,fork的返回值在父进程中返回的是子进程的PID改为

pr = waitpid(pc, NULL, 0);pr = wait(NULL);则父进程将会柱塞,知道子进程退出为止输出:Get child exit code: 14685





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值