一、进程创建
要了解进程如何控制,我们首先要创建出一个进程,在这里就要用到一个函数。
pid_t fork();
fork函数是在进程中,创建一个子进程,创建成功后给父进程返回子进程的id,给子进程返回0,若失败就返回-1。
函数使用过程如下代码:
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<unistd.h>
4 int main()
5 {
6 pid_t pid =fork();
7 if(pid == -1)
8 perror("pid");
9 else if(pid == 1)
10 printf("i am father!pid = %d\n",getppid());
11 else
12 printf("i am child!pid = %d\n",getpid());
13 return 0;
14 }
如左图为运行结果。
由程序代码和执行结果我们可以发现,在if和else的两个语句都执行了,这是为什么呢?
因为fork函数的存在,在原进程的基础上创建了一个新的进程,新的进程则为子进程,原进程称之为父进程。
子进程的代码与父进程一致,代码也相同,但由于返回值的不同,子进程与父进程执行了不同的语句,就造成了图中的结果。
二、进程等待:
对于基于父进程创建的子进程,如果子进程退出后,父进程不对他进行回收的话,他就会变成僵尸进程,之后我们也无法去杀死这个进程了,因此,我们需要在子进程退出后,父进程能够接受他的退出信息并对他进行回收,来保证不占用空间和防止内存泄漏,这里就要使父进程去等待子进程。
进程等待我们使用到的函数为:
pid_t wait(int* status);
返回值,若成功返回等待进程的ID,失败则返回-1。
wait函数的参数是一个输出型参数,来获取子进程退出的状态。
#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid = fork();
if(pid<0)
perror("fork");
else if(pid ==0 )
{
printf("i am child,pid = %d\n",getpid());
sleep(15);
exit(1);
}
else
{
int num;
printf("i am father,pid = %d\n",getppid());
pid_t ret = wait(&num);
if(ret>0&&(num&0x7f==0))
printf("wait success!\n");
} }
上面为测试代码,结果如下
由图能看出来父进程在子进程运行完后,才出现了wait success字样,证明这段代码是在子进程结束后才运行的。
我们可以打开一个新的终端,杀死子进程,结果如下
这次并没有出现wait success字样,因为子进程被杀死了
三、进程终止
进程终止分为正常终止和异常终止
正常终止一般为main函数返回,调用exit,_exit和_Exit函数。
异常终止一般为调用abort函数,接到信号并终止。