Linux学习之进程fork()、exec、exit()/_exit()、wait()/waitpid

fork()函数

进程是一个程序的一次执行的过程。它和程序是有本质区别的,程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念;而进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和消亡的整个过程。它是程序执行和资源管理的最小单位。
在Linux中从已存在的进程中创建一个新的进程唯一方法是使用fork()(或vfork(),下一篇笔记将介绍它们的区别),原来存在的进程为父进程,新创建的进程为子进程,fork()函数执行一次返回两个值,子进程返回0,父进程返回子进程的PID,出错返回-1;使用fork()创建的子进程就是父进程的一个复制品,子进程继承了整个进程的地址空间,包括进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等。下面是《Linux_C一站式学习》中的例子:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
        pid_t pid;
        char *message;
        int n;
        pid = fork();
        if (pid < 0) {
                perror("fork failed");
                exit(1);
        }
        if (pid == 0) {
                message = "This is the child\n";
                n = 6;
        } else {
                message = "This is the parent\n";
                n = 3;
        }
        for(; n > 0; n--) {
                printf(message);
                sleep(1);
        }
        return 0;
 }

执行结果是

This is the child
This is the parent
This is the child
This is the parent
This is the child
This is the parent
This is the child
This is the chil
This is the child

程序的运行过程是
这里写图片描述
详细说明看《Linux_C一站式学习》。

exec函数族

exec函数主要用于在进程中启动另一个程序执行的方法,exec函数族是6个以exec字母开头的函数,这6个函数执行成功不返回,只有出错时返回-1,它们就是:

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const 
envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *

下面对这些函数参数进行说明:
(1)通过对比这些函数,发现只有函数名的第五和第六位的字母不一样,首先看不带字母“p”的函数,第一个参数必须是可执行程序的绝对路径或相对路径,而不能是文件名,这个路径就是PATH环境变量的值;
(2)带有字母“l ”(表示list )的exec函数要求将新程序的每个命令行参数都当作一个参数传给它,命令行参数的个数是可变的,因此函数原型中有… ,… 中的最后一个可变参数应该是NULL,起sentinel的作用;
(3)带有字母“v”(表示vector )的函数,则应该先构造一个指向各参数的指针数组,然后将该数组的首地址当作参数传给它,数组中的最后一个指针也应该是NULL,就像main函数的argv参数或者环境变量表一样;
(4)以“e” (表示environment )结尾的exec函数,可以把一份新的环境变量表传给它,其他exec函数仍使用当前的环境变量表执行新程序。
(5)下面是《嵌入式Linux应用程序开发详解(完整版_第1-12章)》两个应用实例

/*execlp.c*/ 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
      if(fork()==0){ 
/*调用execlp函数,这里相当于调用了“ps -ef”命令*/ 
        if(execlp("ps","ps","-ef",NULL)<0) 
             perror("execlp error!"); 
      } 
}
/*execl.c*/ 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

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

exit()/_exit()

exit()和_exit()都是用来无条件中止进程,但它们是有区别的
这里写图片描述
从图片可以看出在调用exit()比exit()时多做了些清理、保存工作,最后执行exit()中止进程执行;而_exit()则是直接执行exit()中止进程执行。下面是《嵌入式Linux应用程序开发详解(完整版第1-12章)》两个应用实例

/*exit.c*/ 
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
      printf("Using exit...\n"); 
      printf("This is the content in buffer"); 
      exit(0); 
}
/*exit.c*/ 
#include <stdio.h> 
#include <stdlib.h> 

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

wait()/waitpid()

wait()和waitpid()的作用是阻塞调用wait()和waitpid()函数的进程,直到一个子进程结束或者该进程接到了一个指定的信号为止,如果该父进程没有子进程或者他的子进程已经结束,则wait()就会立即返回。

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值