1、fork函数与vfork函数的区别,vfork函数创建的子进程与父进程共享地址空间,包括代码段、数据段和堆栈段。vfork产生的子进程一定比父进程先运行。

栈帧:从逻辑上讲,栈帧就是一个函数执行的环境,它包括函数参数、函数的局部变量、函数执行完回到哪里等。是编译器实现函数调用的一种数据结构。

使用vfork函数后,子进程对父进程的影响是巨大的。其同步措施是必须的。由此,可以理解线程之间的同步是多么的重要。

2、退出进程

        当退出一个进程时,需要调用退出函数。退出函数会深入到内核注释掉进程的内核数据结构,并释放进程所占用的资源。linux环境下使用exit函数退出进程,c程序中的return语句会被翻译为调用exit函数。例如,return 1;会被翻译为exit 1;

        使用exit函数检查进程出错信息。通常exit函数的参数是进程退出的状态,正常退出,参数是0;异常非0。用户也可以把errno变量传给exit函数,这样在程序退出后可以检查程序出错的原因。利用”echo $?“命令。

        exit函数与内涵函数的关系。exit函数是一个标准的库函数,其内部封装了linux系统调用_exit函数。

        设置进程所有者。setuid函数可以设置进程的实际用户ID和有效用户ID。seteuid函数可以实现只修改有效用户ID。

3、执行一个新程序。linux环境下使用exec函数执行一个新程序。该函数在文件系统中搜索指定路径的文件,并把该文件的内容复制到调用exec函数的地址空间,取代原来进程内容。linux系统提供了6中exec函数的泛型。

4、在linux环境编程中,往往需要调用shell命令进行一些操作。linux环境下使用system函数调用shell命令,可以方便的完成一些功能,例如,可以使用system函数在程序中执行ls命令,代替复杂的opendir函数和readdir函数。其函数原型如下:

#include <stdlib.h>

int system(const char* cmdstring);

参数cmstring是需要执行的shell命令。

system函数的实现。首先由调用system函数的进程创建一个子进程,并调用wait函数等待子进程执行完毕;然后,由子进程调用exec函数加载shell运行cmdstring中指定的命令。

5、关系操作

        进程与进程之间是有关系的。必如父子进程、兄弟进程。父进程可以得到子进程退出时的状态。得到进程退出状态这样信息的操作叫做关系操作。在linux环境下使用wait函数得到子进程的结束信息,其函数原型如下:

#include <sys/wait.h>

pid_t wait(int * statloc);

调用wait函数的进程会阻塞,直到该进程的任意一个子进程结束。wait函数会得到该结束的子进程的信息并且返回该子进程的进程ID,结束信息保存在statloc所指向的内存空间中。但wait函数只能等待第一个结束的子进程,如果等待一个指定的子进程用waitpid函数。

僵尸进程:当子进程退出时,退出状态信息保存在内核中,子进程的进程ID也保存在系统的进程列表中,这时的进程被称作僵尸进程。僵尸进程的影响,注意在系统中是有进程数限制的。僵尸进程的产生:当父进程调用fork函数创建一个子进程而不调用wait函数时,一个僵尸进程就诞生了。因为如果父进程没有调用wait函数取得子进程的结束状态信息,就会产生僵尸进程。结束信息被父进程接收后,子进程就不会出现在进程列表中。

避免僵尸进程的避免:作为一个系统的守护进程,init进程被设计成永远调用wait函数。也就是说init进程的子进程不会成为僵尸进程。因此,用户可以使用这种方式避免僵尸进程的产生。注:任何父进程先于子进程退出的子进程都会成为init进程的子进程。