★进程标识符
   

        每个进程都有非负的×××表示唯一的进程ID。下面是一些标识符:
               pid:调用进程的ID(获取方式getpid)
                 ppid:调用进程的父进程ID(获取方式getppid)
                 uid:调用进程的实际用户ID(获取方式getuid)
                 euid:调用进程的有效用户ID(获取方式getuid)
                 gid:调用进程的实际组ID(获取getgid)
                 egid:调用进程的有效组ID(获取getegid)


例:用fork创建子进程,查看父子进程的pid、ppid、uid、euid。

再谈‘进程’_进程


运行结果:

再谈‘进程’_进程_02



★进程创建

      上篇博客中提到可以使用fork( )和execve( )来创建,我们能够知道fork后的子进程能够获得父进程的数据空间、堆、栈的副本,父子进程同时共享文本段。所以说:子进程不能改变父进程中某个变量的值,内核只能修改内存副本中该变量的值。


例:

再谈‘进程’_进程_03


运行结果:

再谈‘进程’_标识符_04


      由上面的程序结果能够看到,子进程对变量的值进行更改,但是并没有影响到父进程中变量的值。一般父进程和子进程执行的先后顺序是不确定的,取决于系统的调度算法。上面的程序父进程先sleep,使得子进程先执行。


     这里再介绍一下vfork( )函数,vfork和fork都能够创建一个子进程,但是vfork的子进程不会将父进程的地址空间进行复制,所以子进程会先执行,在其调用exec后或者exit后,父进程才可以执行。


例:

再谈‘进程’_进程创建_05


运行结果:

再谈‘进程’_进程_06



★进程等待

     进程等待可以使用两个函数wait和waitpid。调用之后会产生以下的一些情况:

             (1)如果所有的子进程都处于运行状态,则会阻塞。

               (2)如果一个子进程已经终止,正在等待父进程获取其状态,则取得该子进程的终止状态立即返回。

               (3)如果它没有任何的子进程,则立即出错返回。


头文件:#include <sys/types.h>                  #include <sys/wait.h>                

              ① pid_t wait (int* status);

              ②pid_t waitpid(pid_t pid, int* status, int options);


     wait函数如果成功,则返回被等待进程的pid,失败返回-1,waitpid函数正常返回收集到的子进程的ID,失败返回-1.