一、进程标识符
#include<unistd.h>
pid_t getpid(void);
返回值:调用进程的进程ID
pid_t getppid(void);
返回值:调用进程的父进程ID
uid_t getuid(void);
返回值:调用进程的实际用户ID
uid_t geteuid(void);
返回值:调用进程的有效用户ID
gid_t getgid(void);
返回值:调用进程的实际组ID
gid_t getegid(void);
返回值:调用进程的有效组ID
二、创建进程fork函数
#include<unistd.h>
pid_t fork(void);
返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1
子进程和父进程继续执行fork调用之后的指令,子进程是父进程的副本。父、子进程共享正文段。
文件共享:
fork的一个特性是父进程的所有打开文件描述符都被复制到子进程中。父子进程的每个相同的打开描述符共享一个文件表项。
除了打开文件外,父进程的很多其他属性也由子进程继承,包括
(1)实际用户ID、实际组ID、有效用户ID、有效组ID
(2)附加组ID
(3)进程组ID
(4)会话ID
(5)控制终端
(6)设置用户ID标志和设置组ID标志
(7)当前工作目录
(8)根目录
(9)文件模式创建屏蔽字
(10)信号屏蔽和安排
(11)针对任一打开文件描述符的在执行时关闭(close-on-exec)标志
(12)环境
(13)连接的共享存储段
(14)存储映射
(15)资源限制
父、子进程之间的区别是:
(1)fork的返回值
(2)进程ID不同
(3)两个进程具有不同的父进程ID
(4)子进程的tms_utime、tms_stiem、tms_cutime以及tms_ustime均被设置为0
(5)父进程设置的文件锁不会被子进程继承
(6)子进程的未处理的闹钟被清除
(7)子进程的未处理信号集设置为空集
创建进程vfork函数
vfork用于创建一个新进程,而该新进程的目的是exec一个新程序,在子进程调用exec或exit之前,它在父进程的地址空间运行。
vfork与fork的另一个区别:vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被高度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
exit函数
如果父进程在子进程之前终止,对于父进程已经终止的所有进程,它们的父进程都改变为ini进程。只要有一个子进程终止,init就会调用一个wait函数取得其终止状态。
一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占有的资源)的进程被称为僵死进程(zombie)。内核为每个终止子进程保存了一定量的信息,所以当终止进程的父进程调用wait或waitpid时,可以得到这些信息。
wait和waitpid函数
当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。调用wait或waitpid时可能发生的情况:
(1)如果其所有子进程都还在运行,则阻塞
(2)如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回
(3)如果它没有任何子进程,则立即出错返回
#include<sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
两个函数返回值:若成功则返回进程ID,若出错则返回-1
两个函数的区别:
(1)在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞
(2)waitpid并不等待在其调用之后的第一个终止子进程,它有若干选项,可以控制它所等待的进程
两个函数的statloc是一个整形指针,可通过宏检查终止状态。
pid参数作用解释:
pid == -1 等待任一子进程。就这一方面而言,waitpid与wait等效
pid > 0 等待其进程ID与pid相等的子进程
pid == 0 等待其组ID等于调用进程组ID的任一子进程
pid < -1 等待其组ID等于pid绝对值的任一子进程
exec函数
当进程调用一种exec函数时,该进程执行的程序会完全替换为新程序,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的ID并未改变。exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段。
#include<unistd.h>
int execl(const char *pathname, const char *arg0, ... /* (char *) 0 */);
int execv(const char *pathname, char *const argv[ ]);
int execle(const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[ ] */);
int execve(const char *pathname, char *const argv[ ], char *const envp[ ]);
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */);
int execvp(const char *filename, char *const argv[ ]);
六个函数的返回值:若出错则返回-1,成功则不返回值
注:
如果filename中包含/,则将其视为路径名(与execl或execv一样?)
否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件。
(l表示list,v表示矢量vector,p表示该函数取filename作为参数),以e结尾的两个函数可以传递一个指向环境字符串指针数组的指针。