我们知道,程序就是一个包含可执行代码的文件,是一个静态的文件。
进程就是可执行程序的一次执行过程,是一个动态的概念,在Linux系统中所有运行的东西都可以称之为进程。
进程的基本状态三种:运行态、就绪态和阻塞态(或等待态)。
下面我们来介绍一下进程控制中的相关函数:
1、fork函数
fork函数的功能是产生子进程,子进程会完全复制父进程的资源,并且子进程的执行完全独立于父进程,调用一次会有两个返回值,在子进程里面返回0,在父进程里面返回子进程的pid号,fork函数存在于头文件#include
一个简单的例子:
#include
#include
#include
int main(){
int p_id;
p_id=fork( );
if (p_id==0)
printf("child process\n");
else
printf("parent process\n");
}
在这里需要注意的是fork函数创建进程以后父子进程所随机运行的,并没有谁先谁后一说。所以如果父进程先结束,子进程就变成了孤儿进程,这对于一个程序来说是不能允许的错误,所以如果希望父进程在子进程结束后再结束,可以使用wait函数:
pid_t wait (int * status); (头文件: wait.h)
wait函数会“暂停”目前进程的执行,直到有信号来到或子进程结束
如果在调用 wait()时子进程已经结束,则 wait()会“立即”返回子进程结束状态值,如果有错误发生则返回返回值-1。失败原因存于 errno 中。
子进程的结束状态值(如exit函数中的值)会存放在参数 status 中, 而wait函数的返回值是子进程的进程号
waitpid:pid_t waitpid(pid_t pid, int * status, int options);
等待指定的子进程结束
简单的例子:
int main()
{ pid_t pc, pr;
pc=fork();
if(pc<0) printf("Error fork.\n");
else if(pc==0){
sleep(10);
exit(0);
}
else{
pr = waitpid(pc, NULL, 0);
if(pr==pc)
printf("Get child %d\n",pr);
else
printf("some error occured.\n");
}
}
这样父进程就会在子进程执行结束以后再执行。
下面我们来探讨一下更高级的问题,如何来创建多个子进程呢,我们知道父子进程都会执行除了进程控制的其他语句,如果我们直接调用fork函数就会创建数不清的进程,比如:
int main(){
int p_id;
p_id=fork( );
if (p_id==0)
printf("child process 1\n");
else
{
wait();
printf("parent process 1\n");
}
p_id=fork( );
if (p_id==0)
printf("child process 2\n");
else
{
wait();
printf("parent process 2\n");
}
}
那么如何避免这种情况呢,最简单的方法就是使用进程链:
#include
#include
#include
int main(){
int i;
pid_t child_pid;
for(i=1;i<3;i++)
{
child_pid = fork();
if( child_pid==0 )
{ printf( "do something \n"); return 0;}
else{ wait(); }
}
return 0;
}
我们用一个return语句来退出if语句执行下一个进程创建函数,这样就避免了子进程在创建子进程的操作。